16题:求三个数之和,令其与给定的target最接近,输出这个值。
这种求几个数之和等于target类问题,总结一个套路就是: 先排序,然后for循环,层层递进。
自己的解法很蠢:设了i、j、k三个指针,三个for循环在移,复杂度很高,超时。
discuss里看到的一个复杂度o(n^2)的解法:思路就是先从小到大排序,然后固定一个指针(i),另外两个指针j从前往后,k指针从后往前,根据sum大于或小于target决定是j往后移还是k往前移。
class Solution:
def threeSumClosest(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
nums.sort()
res = nums[0]+nums[1]+nums[2]
for i in range(len(nums)-2):
j,k = i+1,len(nums)-1
while(j<k):
sum1 = nums[i]+nums[j]+nums[k]
if sum1==target:
return sum1
if abs(sum1-target)<abs(res-target):
res = sum1
if sum1>target:
k-=1
elif sum1<target:
j+=1
return res
15. 3Sum
求出所有三个数之和为0的组合。
思路其实和上面的16题很像,都是指针i固定,指针j和k分别从前往后,从后往前移。这个题有个细节需要注意:就是如果数组中出现重复的数字,需要剔除掉(不然会出现重复的结果)
【大写的attention】:
if nums[i]==nums[i+1]:
和if i > 0 and nums[i] == nums[i-1]:
不是一回事!!后者才是正确的,如果写成了前者,就变成了如果出现重复的数字,直接就忽略了前面的。像[-1,-1,2]这种组合,第一种写法就检测不出来。而第二种写法,说明在前一轮循环中,已经将这个组合求出来了,这里只是为了避免重复。所以两者是有本质区别的!
class Solution:
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
nums.sort()
res = []
for i in range(len(nums)-2):
# if nums[i]==nums[i+1]:
# continue
if i > 0 and nums[i] == nums[i-1]:
continue
j,k=i+1,len(nums)-1
while(j<k):
tmp = nums[i]+nums[j]+nums[k]
if tmp>0:
k-=1
elif tmp<0:
j+=1
else:
res.append([nums[i],nums[j],nums[k]])
while(j<k and nums[j]==nums[j+1]):
j+=1
while(i<k and nums[k]==nums[k-1]):
k-=1
j+=1
k-=1
return res