LeetCode #15 2018-07-27

2018-07-27  本文已影响0人  40巨盗

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
上一篇下一篇

猜你喜欢

热点阅读