LeetCode第15題-三数の和

5638 ワード


1.テーマ
2.テーマの分析と構想
3.考え方
 
1.テーマ
n個の整数を含む配列numsを与え,numsにa,b,cの3つの要素が存在するか否かを判断し,a+b+c=0とする.条件を満たし、繰り返さないすべての三元グループを見つけます.
注意:答えに重複する三元グループは含まれてはいけません.
例えば、所与の配列nums=[−1,0,1,2,−1,−4],
要求を満たす三元群の集合は,[−1,0,1],[−1,−1,2]]である.
2.考え方
この問題で最も直接思いついたのは2数の和で、2数の和はやはり比較的基礎的で、通知記録の方式を採用して、1つの辞書を維持して、新しい数がこの辞書の鍵に属するかどうかを見ることができます.三数の和も似たような方法を使うことができますが、テーマが要求しているのは繰り返してはいけません.これは難しいです.それはまずそれを並べ替えてから、彼らが集合中かどうかを判断するだけで、考えが明らかになります.コードは以下の通りです.
def threeSum(self, nums: List[int]) -> List[List[int]]:
        result = []
        for i,j in enumerate(nums):
            temp = nums[:i]+nums[i+1:]
            dic1 = {}
            dic2 = {}
            for count,k in enumerate(temp):
                if k not in dic1:
                    dic1[-j-k] = k
                else:
                    dic2[tuple(sorted([j,k,-j-k]))] = [j,k,-j-k]
        return dic2.values()

3.改善
しかし残念なことに、この複雑さは高すぎて、すべてのcaseを走ることができなくてタイムアウトして、その前に私が使ったのはlistがlistの中にあるかどうかを判断することで、このようにすると更にすべてのcaseを通じて、複雑さは高すぎて、最適化してから辞書を使うのですが、まだ0だらけのcaseで失敗しました.
修正後といくつかの境界条件を経て、caseを通過したが、極めて遅い解法を与え、私はそれを非情解法と呼んでいる.
def threeSum(self, nums: List[int]) -> List[List[int]]:
        dic2 = {}
        if (len(set(nums) ) == 1)and (len(nums) > 2): #       0    ,  0               
            if 0 in set(nums):
                return [[0,0,0]]
        for i,j in enumerate(nums):
            temp = nums[:i]+nums[i+1:]
            dic1 = {}
            for count,k in enumerate(temp):
                if k not in dic1:
                    dic1[-j-k] = k
                else:
                    dic2[tuple(sorted([j,k,-j-k]))] = [j,k,-j-k]
        return dic2.values()

次に正しい解法を示し,二重ポインタを用いる
 
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums = sorted(nums)
        res = []
        dic1 = {}
        for i,j in enumerate(nums):
            if j > 0:
                continue
            temp = nums[i+1:]
            left = 0
            right = len(temp)-1
            while(left < right):
                
                if j + temp[left]+temp[right] == 0:
                    dic1[(j,temp[left],temp[right])] = [j,temp[left],temp[right]]
                    # res.append([j,temp[left],temp[right]])
                    right -= 1
                elif j + temp[left]+temp[right] > 0:
                    right -= 1
                else:
                    left += 1
        return dic1.values()