您的位置:首页 > 其它

leetcode 3Sum

2015-11-30 12:26 281 查看
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<ba, 遍历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.

参考/article/4982505.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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: