首页 > 学院 > 开发设计 > 正文

[Leetcode] 15. 3Sum

2019-11-14 09:07:33
字体:
来源:转载
供稿:网友

PRoblem:

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: 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] ]

思路 1. 暴力枚举法+分类讨论法。这种题直接暴力枚举的话,时间复杂度高达O(n^3),所以我一开始对暴力枚举加上了分类讨论。三个数之和为0有以下几种情况:

情况 负数个数 零个数 正数个数
1 2个 0个 1个
2 1个 0个 2个
3 1个 1个 1个
4 0个 3个 0个

因此,首先对输入的数组进行“正数,零,负数”分类,然后再穷举这四种情况的所有组合。最后发现,时间复杂度仍然接近O(n^3),这优化意义不大。

#Note: 以下两种方法是题目“2sum”的延伸。“2sum”求的是:对于输入的数组,求出两数之和等于某特定值的所有组合。在这题目“3sum”中,因为题目是求a,b,c使得a+b+c=0,所以我们可以看作是求a,b使得a+b=-c。这样其实就是穷举版的“2sum”问题。 2. 借助hash表。对输入的数组放入一个哈希表中,然后遍历哈希表的每一个数a,然后调用2sum函数:新建一个用于标记的集合set,遍历输入数组的每一个值b(此时要去掉一个数a,因为数具有不可复用性),判断集合set中是否存在一个数c,使得c = -a-b。如果有,则为目标答案,加到result list中;如果没有,则把b数加入到集合set中。 这样做的好处在于减少了一层循环,使得时间复杂度降为O(n^2),但同时空间复杂度是O(n)。另外,调用2sum函数时,也可以遍历已建立好的hash表,可以更节省时间。不过需要注意的是要考虑[0,0,0]这种情况。 3. 双向游标法。首先将输入数组nums排序,然后遍历输入数组的每个数a作为target值,然后调用2sum函数:对于有序数组(除去数a),定义两个指针指向首尾两端,即,一个指向nums[0],一个指向num[len(nums)]。然后有如下三种情况: (1) 若当前和小于-a,则左指针右移; (2) 若当前和大于-a,则右指针左移; (3) 若当前和等于-a,则为目标答案。 这里排序的时间复杂度为O(nlogn),遍历的时间复杂度为O(n^2),所以总的时间复杂度近似于O(n^2).

Solution :

方法2

# -*- coding: utf-8 -*-"""Created on Sat Feb 04 22:30:34 2017@author: liangsht"""def find2Sum(self,target,newdict): hashset = set() for item in newdict.keys(): remain = target - item if remain in hashset: if remain != item: self.myappend([-target,item,remain]) elif newdict[item] >= 2: self.myappend([-target,item,remain]) else: hashset.add(item)class Solution(object): res = [] def myappend(self,occupylist): occupylist.sort() if occupylist not in self.lll: self.res.append(occupylist) def threeSum(self, nums): self.res = [] numslen = len(nums) if numslen <= 2: return [] hashdict = dict() hashdict[int(nums[0])] = 1 for i in xrange(1, numslen): #construct a hash map for list nums if nums[i] in hashdict.keys(): hashdict[nums[i]] += 1 else: hashdict[nums[i]] = 1 for item in hashdict.keys(): if item == 0 and hashdict[item] >=3: self.myappend([0,0,0]) continue target = 0-item newdict = hashdict.copy() hashdict[item] -= 1 if hashdict[item] == 0: newdict.pop(item) find2Sum(self,target,newdict) return self.res

方法3

def threeSum(self, nums): res = [] nums.sort() for i in xrange(len(nums)-2): if i > 0 and nums[i] == nums[i-1]: continue l, r = i+1, len(nums)-1 while l < r: s = nums[i] + nums[l] + nums[r] if s < 0: l +=1 elif s > 0: r -= 1 else: res.append((nums[i], nums[l], nums[r])) while l < r and nums[l] == nums[l+1]: l += 1 while l < r and nums[r] == nums[r-1]: r -= 1 l += 1; r -= 1 return res

ref: 1. CSDN bolg 2. leetcode discussion


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表