leetcode 3Sum

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

Note1

这里可以利用two sum binary search的方法,对于每一个i,利用j, k two pointers 去找sum 等于-nums[i].

Note2

如果是O(N^2)的遍历,要思考是否可以sort一下,然后用two pointers. 因为最后只返回不重复的值,例如,如果 a<b , 遍历a的时候会找到(a,b),遍历b的时候会找到a,所以只要sort一下,遍历到a的时候,只需要遍历a以后的值就行。这样没有降低复杂度,依然还是N^2的方法。但是可以有效的去重复,并且还要注意i,j,k 在遍历的时候对应的元素也要去重复。

sort之后就有大小关系,就可能只需要遍历一部分或者可以减枝

另一个sort的原因就是题目要求Elements in a triplet (a,b,c) must be in non-descending order.

参考http://www.cnblogs.com/zuoyuan/p/3699159.html

解题思路:1,先将数组排序。

     2,排序后,可以按照TwoSum的思路来解题。怎么解呢?可以将num[i]的相反数即-num[i]作为target,然后从i+1到len(num)-1的数组元素中寻找两个数使它们的和为-num[i]就可以了。下标i的范围是从0到len(num)-3。

     3,这个过程要注意去重。就是说j指向的数可能有很多个,k指向的数也有很多个

     4,时间复杂度为O(N^2)。

class Solution:
    # @return a list of lists of length 3, [[val1,val2,val3]]
    def threeSum(self, num):
        num.sort()
        res = []
        for i in range(len(num)-2):
            if i == 0 or num[i] > num[i-1]:#这里因为num已经sort了,所以这里仅仅是说i如果指向了与上一个元素相同的数,那么就continue。我们只考虑第一个。sort了之后也会有相同的值,e.g.{1,1,1,2,2},只考虑第一个1,第一个2
                left = i + 1; right = len(num) - 1
                while left < right:
                    if num[left] + num[right] == -num[i]:
                        res.append([num[i], num[left], num[right]])
                        left += 1; right -= 1
                        while left < right and num[left] == num[left-1]: left +=1#去掉重复值
                        while left < right and num[right] == num[right+1]: right -= 1
                    elif num[left] + num[right] < -num[i]:#如果小于target,那么就要增加num[left] + num[right],因为sorted,所以left向右移就行。
                        while left < right:#这里也是去掉重复值,可以改造不用break
                            left += 1
                            if num[left] > num[left-1]: break
                    else:
                        while left < right:
                            right -= 1
                            if num[right] < num[right+1]: break
        return res

当num[left] + num[right] < -num[i]时,我们可以不用break

                while left < right:
                    if num[left] + num[right] == -num[i]:
                        res.append([num[i], num[left], num[right]])
                        left += 1; right -= 1
                        while left < right and num[left] == num[left-1]: left +=1#去掉重复值
                        while left < right and num[right] == num[right+1]: right -= 1
                    elif num[left] + num[right] < -num[i]:#如果小于target,那么就要增加num[left] + num[right],因为sorted,所以left向右移就行。
                        #print (left,right)
                        while left < right and num[left + 1] == num[left]:
                            left += 1
                        left += 1
                    else:
                        while left < right and num[right - 1] == num[right]:
                            right -= 1
                        right -= 1

参考http://codesays.com/2014/solution-to-3sum-by-leetcode/ 的code
这里要注意i,j,k都要去重复。
my code

class Solution(object):
    def threeSum(self, nums):
        """ :type nums: List[int] :rtype: List[List[int]] """
        if len(nums) < 3:
            return []

        nums.sort()
        #after sort(), we just need two pointers to scan
        res = []
        i = 0
        while i < len(nums) - 2:        
            j = i + 1
            k = len(nums) - 1
            while j < k:
                if nums[i] + nums[j] + nums[j] > 0 or nums[i] + nums[k] + nums[k] < 0:
                    break
                if nums[i] + nums[j] + nums[k] == 0:
                    res.append([nums[i], nums[j], nums[k]])
                    j += 1
                    while j < k and nums[j] == nums[j - 1]:
                        j += 1
                    k -= 1
                    while k > j and nums[k] == nums[k + 1]:
                        k -= 1
                elif nums[i] + nums[j] + nums[k] < 0:
                    j += 1
                    while j < k and nums[j] == nums[j-1]:   j += 1
                else:
                    # Skip duplicate num[k+1]
                    k -= 1
                    while k > j and nums[k] == nums[k+1]:   k -= 1
            i += 1
            while i < len(nums) - 2 and nums[i] == nums[i - 1]:
                i += 1
        return res

你可能感兴趣的:(LeetCode)