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
相关文章推荐
- [LeetCode] K sum(2Sum、3Sum、4Sum)
- Leetcode 2SUM-3SUM-4SUM
- leetcode--sum集合:2sum,3sum,4sum
- Leetcode 1. Two Sum & 15. 3Sum & 16. 3Sum Closest & 18. 4Sum
- LeetCode 2Sum, 3Sum, 4Sum
- LeetCode之“散列表”:Two Sum && 3Sum && 3Sum Closest && 4Sum
- LeetCode Two Sum、3Sum、3Sum Closest、4Sum
- Summary for leetcode 2Sum, 3Sum, 4Sum, K Sum
- LeetCode解题报告--2Sum, 3Sum, 4Sum, K Sum求和问题总结
- 2016/10/28 很久没更了 leetcode解题 3sum问题进阶版4sum
- leetcode 3sum closest && 4sum
- 【C++】【LeetCode】15. 3Sum & 16. 3Sum Closest & 18. 4Sum
- 求和问题总结(leetcode 2Sum, 3Sum, 4Sum, K Sum)
- [leetcode] 求和问题总结(2Sum, 3Sum, 4Sum, K Sum)
- 求和问题总结(leetcode 2Sum, 3Sum, 4Sum, K Sum)
- [LeetCode] Two Sum, 3Sum ,3SumCloset , 4Sum
- Sum—LeetCode-18 4Sum
- 2sum、3sum、4sum以及任意连续的数的和为sum、任意连续或者不连续的数的和为sum
- 2Sum -- Java实现(3Sum 4Sum)待补充
- LeetCode:3Sum, 3Sum Closest, 4Sum