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

    这题是求出三个数字和为0的全部组合。做法很经典,是枚举第一个数字nums[i],后面就转换为求和为-nums[0]的two sum问题。由于要枚举的情况很多,所以对每个第一个数字的位置都采用hashmap不是很现实。先排序,再用two pointer的方法比较合适。这题的重点是如何去重。如果不在前端去掉重复,则在后端放入res的时候,需要对每个新加入的三数组合都需要进行判断,复杂度也很高,(这种后端去重的做法详见4sum这题)这种前期不去重的做法超时。

    考虑前期去重,有两种方案。但是两种方案的共同点都是先对target去重。具体见代码:

    第一种:类似permutation II的处理方法,对于一连串重复只取开始或者结束这个,但是是开始还是结束这个挑选需要留意:

    对于target数字,如果我们把target数字放在最前面,则取连续重复数字中的第一个,这样对于有可能前两个数字一样的组合留出了可能。

    同理如果把target放在最后,则应该取连续重复数字的最后一个,这样对于后两个数字一样的留下可能。

    如果我们把target数字放前面,则再考虑避免l数字重复取,或者r数字重复取。在每次nums[l]+nums[r]==target时,我们同时向右移动l,向左移动r,但是如果移动后还和原数字一样,则会形成重复,所以要跳过。

     class Solution(object):
        def threeSum(self, nums):
            """
            :type nums: List[int]
            :rtype: List[List[int]]
            """
            if not nums or len(nums) < 3:
                return []
            nums.sort()   #先排序
            res = []
            for i in xrange(len(nums)-2):
                if i > 0 and nums[i] == nums[i-1]: #第一个位置的重复值处理
                    continue
                target = 0 - nums[i]
                l = i + 1
                r = len(nums) - 1
                while l < r:
                    if nums[l] + nums[r] < target:
                        l += 1
                    elif nums[l] + nums[r] > target:
                        r -= 1
                    else:
                        res.append([nums[i], nums[l], nums[r]])
                        l += 1
                        r -= 1 #也可以移动到while后面
                        while l < r and nums[l] == nums[l-1]: #第二个位置的重复值处理
                            l  += 1
    # 实际是那个3个数字加起来为0,只需要对其中两个数字去重就可以 # while l < r and nums[r] == nums[r+1]: #第三个位置的重复值处理 # r -= 1
    return res

    复杂度为O(nlogn+n^2) = O(n^2).空间复杂度O(1).

    另外一种去重方案是我们对target去重,但是不对l,r移动中做去重处理,只在添加结果时,在考虑l或者r元素是否重复。

    比如是考察左元素,则检查l == i+1 or nums[l] != nums[l-1] 防止左元素和前面的结果产生重复。

    新写法:

    class Solution(object):
        def threeSum(self, nums):
            """
            :type nums: List[int]
            :rtype: List[List[int]]
            """
            if len(nums) < 3:
                return []
            nums.sort()
            res = []
            for i in xrange(len(nums)-2):
                if i == 0 or nums[i] != nums[i-1]: 
                    target = 0 - nums[i]
                    l = i+1
                    r = len(nums)-1
                    while l < r:     
                        if nums[l]+nums[r] < target:
                            l += 1
                        elif nums[l]+nums[r] > target:
                            r -= 1
                        else:
    # 开头的数字,或者和前面的元素不重合
    if l == i+1 or nums[l] != nums[l-1]: res.append([nums[i],nums[l],nums[r]]) l += 1 r -= 1 return res
  • 相关阅读:
    selenium+phantomjs报错:Unable to find a free port的分析和解决
    hadoop集群搭建
    虚拟机安装CentOS7 Minimal、jdk和hadoop
    Javascript学习笔记-一些关键点
    隐藏 Win10 中的3D对象、文档、音乐、图片、视频、下载、桌面7个文件夹
    白话网页的网络性能
    (转)“拿人钱财,与人消灾”,这才是员工含义的本质
    JS 小工具 MYSQL WHERE IN条件 去掉换行符(列转行)
    PHP 基于redis的分布式锁
    PHP 将json的int类型转换为string类型 解决php bigint转科学计数法的问题
  • 原文地址:https://www.cnblogs.com/sherylwang/p/5627240.html
Copyright © 2011-2022 走看看