leetcode 15&16——三個數求和
阿新 • • 發佈:2018-12-27
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