您的位置:首页 > 其它

[Leetcode] 15. 3Sum

2017-02-05 01:27 411 查看
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有以下几种情况:

情况负数个数零个数正数个数
12个0个1个
21个0个2个
31个1个1个
40个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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode