1. 程式人生 > >LeetCode[Array]----3Sum

LeetCode[Array]----3Sum

integer 遍歷 [] http col word-wrap 兩個指針 article target

3Sum

Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0?

Find all unique triplets in the array which gives the sum of zero.

Note:

  • Elements in a triplet (a,b,c) must be in non-descending order. (ie, abc)
  • The solution set must not contain duplicate triplets.

    For example, given array S = {-1 0 1 2 -1 -4},

    A solution set is:
    (-1, 0, 1)
    (-1, -1, 2)

分析:

該題是LeetCode-Two Sum一題的升級版。

題目的要求是,給定一個數組,要求找到一組不重合的解(a,b,c),使得a + b + c等於0.

借鑒Two Sum題的(編程之美上的)思路,我們能夠將當中的一個數a作為target,然後問題就轉化為了求b + c等於-a的Two Sum問題。

詳細解說一下:我們首先還是對數組nums進行排序。這樣後面查找時就行使用雙指針分別從前和從後向中間開始遍歷了。

在排序後nums中依次從左邊開始選擇一個元素乘以-1作為target,然後使用左右兩個指針分別從前和往後開始遍歷,假設兩指針的相應的元素和等於target。則將這三個元素存儲作為一個解,然後左右指針分別向中間移動;假設兩指針的相應元素和大於target,那麽右指針向左移動。假設兩指針的相應元素和小於target,那麽左指針向右移動。


代碼:

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        res = []
        if len(nums) < 3:
            return []
        # 對數組進行排序。方便後面的查找
        nums.sort()
        for i in range(len(nums) - 2):
            # 把a作為target
            target = nums[i] * -1
            # 問題轉化為b+c == -a的情況了
            a = i + 1
            b = len(nums) - 1
            while a < b:
                if nums[a] + nums[b] == target:
                    res.append([nums[i], nums[a], nums[b]])
                    a += 1
                    b -= 1
                elif nums[a] + nums[b] > target:
                    b -= 1
                else:
                    a += 1
        dummyres = []
        # 因為上面的方法產生的解有反復,須要去重
        for i in range(len(res)):
            if res[i] in dummyres:
                pass
            else:
                dummyres.append(res[i])
        return dummyres


改進一下:

上面的代碼產生的解中有反復,假設我們可以在求解的過程中過濾掉左/右指針移動後的元素值不發生變化這兩種情況。就可以避免在求解過程中產生反復解。


改進的代碼:

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        res = []
        if len(nums) < 3:
            return []
        nums.sort()
        for i in range(len(nums) - 2):
            # 當nums[i]大於0時。後面的元素和一定大於0,不須要再進行推斷了
            # 當nums[i]與前一個元素值同樣時,解是同樣的
            if nums[i] > 0 or i and nums[i] == nums[i-1]:
                continue
            target = -nums[i]
            left = i + 1
            right = len(nums) - 1
            while left < right:
                # 當nums[right]小於0時。a,b,c三個元素值都小於0。也不須要進行-a == b+c的推斷了
                if nums[right] < 0:
                    break
                if nums[left] + nums[right] == target:
                    res.append([nums[i], nums[left], nums[right]])
                    while left < right and nums[left+1] == nums[left]:  # 當nums[left]值與下一個元素值同樣時,解同樣
                        left += 1
                    while left < right and nums[right-1] == nums[right]:
                        right -= 1
                    left += 1
                    right -= 1
                elif nums[left] + nums[right] > target:
                    right -= 1
                else:
                    left += 1
        return res

LeetCode[Array]----3Sum