您的位置:首页 > 其它

Leetcode-2sum,3sum,4sum

2017-07-11 16:35 447 查看
LeetCode有三道题是求一个数组中的数字任意三个或者四个数的和等于目标值的题。最简单,最暴力的方法就是每三个或者四个数都进行尝试,时间复杂度是o(n^3)或是o(n^4),肯定是超时的。主要思想是,利用两个指针进行移动,选取符合条件的数字。
原题4sum如下:


Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note: The solution set must not contain duplicate quadruplets.
For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0.
A solution set is:
[
[-1,  0, 0, 1],
[-2, -1, 1, 2],
[-2,  0, 0, 2]
]


2sum

先看2sum,如果使用暴力破解就是n^2的时间复杂度,如果题目给出一个一维数组
[a,d,f,g,d],列出相加是target的两个
4000
数字的所有组合。这是我写的一个简单的代码,时间复杂度O(n^2).


from collections import Counter
def twosum1(list,target):
if len(list)<2:
return []
result=[]
dict=Counter(list)#统计列表中元素重复次数
while len(list)>2:
print len(list)
one=list[0]
newlist=list[1:]
for second in newlist:
if one+second==target:
result.append([one,second])
print result
break
c=dict[one]
while(c):
list.remove(one)
c-=1#把列表中所有此元素删掉,防止重复
return result


如果给列表先做一个排序时间耗费nlog(n),然后新列表头尾指针,利用两个指针,指向一个最大数,一个最小数,一个最小数,两个指针指向的数的和小于target,则小指针向大的方向移动,反之,大指针向小的方向移动,这个方法耗费时间是n,肯定小于方法一。代码如下:

def twosum2(nums,target):
if len(nums) < 2:
return 0
i = 0
j = len(nums) - 1
result=[]
while i != j:
if nums[i] + nums[j] < target:
i += 1
elif nums[i] + nums[j] > target:
j -= 1
else:
a = [nums[i], nums[j]]
i += 1
while nums[i] == nums[i - 1] and i != j:
i += 1#跳过相同的元素,避免重复
result.append(a)
return result


3sum

3sum在2sum的基础上,可以很轻松地解决这个问题,先选择一个数字作为三个数中的一个one,然后再在剩下的数中找到两个数的和等于target-one的,即可解决这个问题。题目如下:

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.


代码如下:

def threeSum(nums):
nums.sort()#排序
def twosum(target, nums,final):#两个数的和等于target,这里的target即为0-第一个加数
if len(nums) < 2:
return 0
i=0
j=len(nums)-1
while i !=j:
if nums[i]+nums[j]<target:
i+=1#指针向大的方向移动
elif nums[i]+nums[j]>target:
j-=1#指针向小的方向移动
else:
a=[-target,nums[i],nums[j]]#符合要求
i+=1
while nums[i]==nums[i-1]and i!=j:
i+=1#防止重复,把使用过的数字也同时排除
final.append(a)#三个数的组合放入最终的列表里
return final
result = []#存放最终结果的列表
for i in range(len(nums)-2):#选取第一个加数
if i>0 and nums[i]==nums[i-1]:
continue
else:
newnums=nums[i+1:]
target=-nums[i]
result=twosum(target,newnums,result)
return result


4sum

4sum再3sum的基础上再套一个循环,即可解决这个问题,代码如下:

class Solution(object):
def fourSum( self,nums, target):
def threeSum(nums,target):
def twosum(target,num,nums,final):
i=0
j=len(nums)-1
target0=target-num
while i !=j:
if nums[i]+nums[j]<target0:
i+=1
elif nums[i]+nums[j]>target0:
j-=1
else:
a=[num,nums[i],nums[j]]
i+=1
while nums[i]==nums[i-1]and i!=j:
i+=1
final.append(a)
return final
result = []
for i in range(len(nums)-2):
if i>0 and nums[i]==nums[i-1]:
continue
else:
newnums=nums[i+1:]
result=twosum(target,nums[i],newnums,result)
return result
if len(nums) < 4:
return []
nums.sort()
i = 0
result = []
for i in range(len(nums) - 3):
if i>0 and nums[i]==nums[i-1]:
continue
subsum1 = nums[i]
subsum2 = target - subsum1
newlist = nums[i+1:]
thresult = threeSum(newlist, subsum2)
if len(thresult) > 0:
for list in thresult:
list.append(subsum1)
result.append(list)
return result
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: