LeetCode Prob.15 3Sum

先挖坑,补上几个大佬的代码

第一个代码,用的是双指针法,思想靠近于2Sum。

首先,对数组进行排序。

然后,对于以下三种情况,可以直接判断无解:

  • 长度为0(其实可以说长度小于3)
  • 最小数字大于0,即数组全大于0
  • 最大数字小于0,即数组全小于0

接着我们对数组进行遍历。当我们选定了当前点,例如,nums[pt],之后,就有了一个2Sum的目标:0 - nums[pt]

需要注意的是,由于遍历相当于将搜索空间从左边缩小,因此 10 行有个相应的判断条件。

现在我们要做的就是在left =  pt + 1 到 right = len(nums) - 1 之间,寻找2Sum的结果为 0 - nums[pt] 的二元组。

而且,这种寻找方式可以确保,pt, left, right 是单调上升的。

此外,在寻找到了结果之后,还并不能就此结束,因为在寻找到的 left 和 right 的内部还有可能出现满足的二元组。这也是 20 行到 23 行的意义。

并且,我们的寻找,已经找出了 pt + 1 到 len(nums) - 1 之间所有对应 0 - nums[pt]的二元组,所以我们可以在 11 行跳过同等的数字。

其它基本上就没有什么好说的了,如果2Sum的原理不懂可以去看看题目,很简单的。

 1 class Solution:
 2     def threeSum(self, nums: List[int]) -> List[List[int]]:
 3         nums.sort()
 4         #print (nums)
 5         #pre judging
 6         if len(nums) == 0 or nums[0] > 0 or nums[-1] < 0: return []
 7         ans = []
 8         pt = 0
 9         while pt < len(nums) - 2: #there must be 2 numbers ahead 
10             if nums[pt] > 0: break
11             if pt > 0 and nums[pt] == nums[pt - 1]:
12                 pt += 1
13                 continue
14             left = pt + 1
15             right = len(nums) - 1
16             #print (nums[pt], nums[left], nums[right])
17             while left < right:
18                 if nums[pt] + nums[left] + nums[right] == 0:
19                     ans.append([nums[pt], nums[left], nums[right]])
20                     while left < right and nums[left] == nums[left + 1]: left += 1
21                     while left < right and nums[right] == nums[right - 1]: right -= 1
22                     left += 1
23                     right -= 1
24                 elif nums[pt] + nums[left] + nums[right] > 0:
25                     right -= 1
26                 else:
27                     left += 1
28             pt += 1
29         return ans 
30             
31             

 

 1 class Solution:
 2     def threeSum(self, nums):
 3         """
 4         :type nums: List[int]
 5         :rtype: List[List[int]]
 6         """
 7         d = {}
 8         for val in nums:
 9             d[val] = d.get(val, 0) + 1
10         
11         pos = [x for x in d if x > 0]
12         neg = [x for x in d if x < 0]
13         
14         res = []
15         if d.get(0, 0) > 2:
16             res.append([0, 0, 0])
17             
18         for x in pos:
19             for y in neg:
20                 s = -(x + y)
21                 if s in d:
22                     if s == x and d[x] > 1:
23                         res.append([x, x, y])
24                     elif s == y and d[y] > 1:
25                         res.append([x, y, y])
26                     elif y < s < x:
27                         res.append([x, y, s])
28         return res

 

 1 class Solution:
 2     def threeSum(self, nums: 'List[int]') -> 'List[List[int]]':
 3         from bisect import bisect_left, bisect_right
 4        
 5         target = 0
 6         
 7         result = []
 8         length = len(nums)
 9         
10         if length < 3:
11             return result
12         
13         count ={}
14         # map the counts
15         for n in nums:
16             if n in count:
17                 count[n] += 1
18             else:
19                 count[n] = 1
20             
21         keys = list(count.keys())
22         keys.sort()
23       
24         t3 = target // 3
25         if t3 in keys and count[t3] >= 3:
26             result.append([t3, t3, t3])
27 
28         begin = bisect_left(keys, target - keys[-1] * 2)
29         end = bisect_left(keys, target * 3)
30 
31         for i in range(begin, end):
32             a = keys[i]
33             if count[a] >= 2 and target - 2 * a in keys:
34                 result.append([a, a, target - 2 * a])
35 
36             max_b = (target - a) // 2  # target-a is remaining
37             min_b = target - a - keys[-1]  # target-a is remaining and c can max be keys[-1]
38             b_begin = max(i + 1, bisect_left(keys, min_b))
39             b_end = bisect_right(keys, max_b)
40 
41             for j in range(b_begin, b_end):
42                 b = keys[j]
43                 c = target - a - b
44                 if c in count and b <= c:
45                     if b < c or count[b] >= 2:
46                         result.append([a, b, c])
47         return result

 

posted on 2019-02-26 22:27  Ricochet!  阅读(150)  评论(0编辑  收藏  举报