1. 程式人生 > >leetcode 15&16——三個數求和

leetcode 15&16——三個數求和

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