LeetCode[Array]----3Sum

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, 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值