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