• LeetCode[Array]----3Sum


    3Sum

    Given an array S of n integers, are there elements abc 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, a ≤ b ≤ c)
    • 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

  • 相关阅读:
    Python运算符,基本数据类型
    Python2 错误记录1File "<string>", line 1, in <module> NameError: name 'f' is not defined
    用户登录三次练习
    跟我一起学Python-day1(条件语句以及初识变量)
    vim operation
    步步为营-28-事件本质
    步步为营-27-事件
    步步为营-26-多播委托
    步步为营-25-委托(比大小)
    步步为营-24-委托
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/7366840.html
Copyright © 2020-2023  润新知