zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    c#生成验证码
    使用Linq导出数据到execl
    AspNetPager2.0.dll组件的使用
    <httpRuntime>属性值的解析
    帮助文档chm的制作
    关于table边框打印不显示的样式设置
    【Reporting Services 报表开发】— 如何设置报表分页列标题每一页都显示
    Microsoft Dynamics CRM4.0 创建单据的时候,自动生成单据编号的通用方法
    【Reporting Services 报表开发】— 总结
    出现“安全时间戳无效,因为其创建时间(“2013-10-30T14:42:07.861Z”)是将来的时间。当前时间为“2013-10-30T14:36:23.988Z”,允许的时钟偏差是“00:05:00””的原因
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/7366840.html
Copyright © 2011-2022 走看看