美文网首页
LeetCode #15 2018-07-27

LeetCode #15 2018-07-27

作者: 40巨盗 | 来源:发表于2018-07-27 23:32 被阅读0次

    15. 3Sum

    Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
    Note:
    The solution set must not contain duplicate triplets.

    Example:
    Given array nums = [-1, 0, 1, 2, -1, -4],
    A solution set is:
    [
       [-1, 0, 1],
       [-1, -1, 2]
    ]

    https://leetcode.com/problems/3sum/description/

    这道题和Two Sum有所不同,使用哈希表的解法并不是很方便,因为结果数组中元素可能重复,如果不排序对于重复的处理将会比较麻烦,因此这道题一般使用排序之后夹逼的方法,总的时间复杂度为O(n2+nlogn)=(n2),空间复杂度是O(n), 注意,在这里为了避免重复结果,对于已经判断过的数会skip掉,这也是排序带来的方便。 这道题考察的点其实和Two Sum差不多,Two Sum是3Sum的一个subroutine。

    代码如下:

    class Solution(object):
        def threeSum(self, nums):
            """
            :type nums: List[int]
            :rtype: List[List[int]]
            """
            result = []
            if not nums or len(nums) < 3:
                return result
            
            nums.sort()
            for i, num in enumerate(nums[len(nums) - 1:1:-1]):
                cur_index = len(nums) - i - 1
                if cur_index < len(nums) - 1 and nums[cur_index] == nums[cur_index + 1]:
                    continue
                cur_res = self.twoSum(nums, 0, cur_index - 1, -num)
                for res in cur_res:
                    res.append(num)
                result.extend(cur_res)
            
            return result
        
        def twoSum(self, nums, left, right, target):
            cur_res = []
            while(left < right):
                if nums[left] + nums[right] == target:
                    temp_res = [nums[left], nums[right]]
                    cur_res.append(temp_res)
                    left += 1
                    right -= 1
                    while(left < right and nums[left] == nums[left - 1]):
                        left += 1
                    while(left < right and nums[right] == nums[right + 1]):
                        right -= 1
                elif nums[left] + nums[right] < target:
                    left += 1
                else:
                    right -= 1
        
            return cur_res
    

    感悟:

    1. 由于list.append()是从后面进行添加,而且题目要求结果数组中的数字升序,所以最后添加进list的一定要是最大的,所以for循环应该从len(nums) - 1扫到2.
    2. 为了避免结果重复,我们要跳过已经判断过的数:
                if cur_index < len(nums) - 1 and nums[cur_index] == nums[cur_index + 1]:
                    continue
    

    这点很重要,在很多有重复的数组中,为了避免重复的结果产生,都需要使用这个判断。

    1. 因为可能有多组2个数的和为-nums[i], 所以在找到一组后,要跳过重复元素,然后继续寻找。
                  while(left < right and nums[left] == nums[left - 1]):
                        left += 1
                  while(left < right and nums[right] == nums[right + 1]):
                        right -= 1
    

    相关文章

      网友评论

          本文标题:LeetCode #15 2018-07-27

          本文链接:https://www.haomeiwen.com/subject/xotnmftx.html