1. 程式人生 > >三數之和(LeetCode)

三數之和(LeetCode)

給定一個包含 n 個整數的陣列 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?找出所有滿足條件且不重複的三元組。

注意:答案中不可以包含重複的三元組。

例如, 給定陣列 nums = [-1, 0, 1, 2, -1, -4],

滿足要求的三元組集合為:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

'''

這道題因為涉及到好幾個步驟,比較有難度。

我一開始是想按兩數之和的思路暴力過,但是呢,明顯這是行不通的。

後來受到大佬的點撥,回去看了一下兩數之和的解題思路。

發現其實也是可以套用到裡面的。

然後發現最後幾個測試用例真的反人類。。

長度在3000左右,所以沒有好好處理的話,很容易超時。

emmmm。。。雖然過了,但是是卡線過的,所以到最後我會膜拜一下大佬的程式碼

'''

class Solution:
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        if len(nums)<3: return []#長度小於三,無解
        nums = sorted(nums)#排序
        if nums[0]==nums[-1] and nums[0]==0:return [[0,0,0]]#排序完後,全等於零的話,就只有一個答案

        if nums[0]==nums[-1] and nums[0]!=0:return [] #同理,全等於任意非零的一個數的話,沒有答案
        lis = []
        dic = {}
        for i in range(len(nums)):#構造表
            if nums[i] not in dic:
                dic[nums[i]] = i


        for target in range (len(nums)):#將nums遍歷一次,且把nums[target]的值看做兩數之和的target
            for i in range (target+1,len(nums)):#找其它兩個數字
                    q = -(nums[target] + nums[i])
                    w = nums[target]
                    e = nums[i]
                    if q in dic and dic[q] != i and dic[q] != target:
                        lis.append(sorted([w,e,q]))#先把它們放進去,不管重複,然後在最後去重。試過在這裡去重然後超時了。。
        turn_list = []#最後返回的陣列
        dic = {}
        for i in lis:
            if str(i) not in dic:
                dic[str(i)] = 1
                turn_list.append(i)
        return turn_list

'''

最後來膜拜一下大佬的解法

class Solution:
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        res=[]
        d=dict()
        for i in nums:
            if i not in d:
                d[i]=0
            d[i]+=1  #統計數字出現的次數,也是變相的去重了
        posnum=[i for i in d  if i>0 ]#i in d的意思跟 i in d.keys()的效果差不多
        negnum=[i for i in d  if i<0 ]#分開正負
        if d.get(0,0)>2:#這裡的get有兩個引數,第一個0是在關鍵字中查詢返回關鍵字為0的值(即返回統計到0的個數),第二個0的意思是,如果沒有這個關鍵字就返回0。這是算比較高階的用法了。也可以這樣if (0 in d.keys() and d[0]>2):res.append[[0,0,0]]
            res.append([0,0,0])#如果0的個數多於3個,就加一個解進取。能解決倒數第二個測試例超級多0的問題
        if negnum==[] or posnum==[]:#顯然,全負或全正都是沒有答案的,所以return 了
            return res
        for i,x in enumerate(posnum):#遍歷posnum,得到posnum的下標和數字
            if d[x]>=2 and -2*x in d:# 把符合這個等式的放進去x + x + (- 2 * x) = 0
                res.append([x,x,-2*x])
            for y in posnum[i+1:]:#把符合 x + y + (-(x+y)) = 0 放進res
                if -(x+y) in d:
                    res.append([x,y,-x-y])
        for i,x in enumerate(negnum):同上理
            if d[x]>1 and -2*x in d:
                res.append([x,x,-2*x])  
            for y in negnum[i+1:]:
                if -(x+y) in d:
                    res.append([x,y,-x-y])
        
        if 0 in d:#如果d中有0,就看一看是不是存在相反數
            for x in posnum:
                if -x in d:
                    res.append([x,0,-x])
        return res

'''