【算法训练】n数之和 模板解法 python JavaScript
由于JavaScript部分只是为了练习自己对js语法的掌握,所以算法的思路和python完全一样(所以没有写注释),可以忽略不看~一、三数之和 151、分析先考虑两数之和,我们先将数组排序,然后采用头尾双指针,相向逼近找到符合条件的数对。其中很重要的一点,在于去重,如果有重复值,我们应该采用while循环滤掉。对于n数之和,我们可以层层递归到找n-1数之和,一直到n=2的情况。然后层层添加即可。
·
由于JavaScript部分只是为了练习自己对js语法的掌握,所以算法的思路和python完全一样(所以没有写注释),可以忽略不看~
一、三数之和 15
1、分析
先考虑两数之和,我们先将数组排序,然后采用头尾双指针,相向逼近找到符合条件的数对。其中很重要的一点,在于去重,如果有重复值,我们应该采用while循环滤掉。
对于n数之和,我们可以层层递归到找n-1数之和,一直到n=2的情况。然后层层添加即可。
具体见代码中的注释。
2、代码
class Solution:
def targetSum(self,nums,n,start,target): #用于寻找n数之和的递归函数
sz = len(nums)
res = []
if n<2 or sz<n: #递归出口
return res
if n==2: #最基础的情况
lo,hi = start,sz-1 #首尾双指针相向而行进行寻找
while lo<hi:
temp = nums[lo]+nums[hi]
left = nums[lo] #用于后续去重
right = nums[hi]
if temp < target:
while lo<hi and nums[lo]==left: #用while循环滤除重复值
lo += 1
elif temp>target:
while lo<hi and nums[hi]==right:
hi -= 1
elif temp == target:
res.append([nums[lo],nums[hi]]) #找到符合条件的数对,加入结果集
while lo<hi and nums[lo]==left: #同样要进行while循环滤除重复
lo += 1
while lo<hi and nums[hi]==right:
hi -= 1
else:
i = start #当n大于2时,进行递归求解
while i<sz:
origin = nums[i]
sub = self.targetSum(nums,n-1,i+1,target-nums[i]) #递归找到n-1数之和的结果集
for t in sub: #加入当前值,即为完整n数之和结果集
t.append(nums[i])
res.append(t[:])
while i<sz and nums[i]==origin: #由于结果集层层返回的都是没有重复的,此处枚举的时候也要保证无重复,从而保证每个环节都没有重复
i += 1
return res
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort() #记住先对数组进行排序
return self.targetSum(nums,3,0,0) #要求的是三数之和,起点为0,目标和为0
JS
/**
* @param {number[]} nums
* @return {number[][]}
*/
var threeSum = function(nums) {
nums.sort((a,b)=> a-b); #注意js的排序
return targetSum(nums,3,0,0);
};
var targetSum = function(nums,n,start,target) {
let sz = nums.length;
let res = [];
if(n<2 || n>sz){
return res;
}
if(n == 2){
let lo=start;
let hi = sz-1;
while(lo<hi){
let sum_ = nums[lo]+nums[hi];
let left = nums[lo],right = nums[hi];
if(sum_<target){
while(lo<hi && nums[lo]==left){
lo ++;
}
}else if(sum_ > target){
while(lo<hi && nums[hi]==right){
hi --;
}
}else{
res.push([nums[lo],nums[hi]]);
while(lo<hi && nums[lo]==left){
lo ++;
}
while(lo<hi && nums[hi]==right){
hi --;
}
}
}
}else {
let i = start;
while(i<sz){
let old = nums[i]
let sub = targetSum(nums,n-1,i+1,target-nums[i]);
for(let temp of sub){
temp.push(nums[i])
res.push(temp)
}
while(i<sz && nums[i]==old){
i ++;
}
}
}
return res;
}
二、四数之和
1、分析
本题完全可以直接复用上一题的代码,思路完全相同。采用递归解法即可。
2、代码
class Solution:
def targetSum(self,nums,n,start,target): #功能函数与上一题完全相同
sz = len(nums)
res = []
if n<2 or n>sz:
return res
if n==2:
lo,hi = start,sz-1
while lo<hi:
sum_ = nums[lo]+nums[hi]
left,right = nums[lo],nums[hi]
if sum_<target:
while lo<hi and nums[lo]==left:
lo += 1
elif sum_>target:
while lo<hi and nums[hi]==right:
hi -= 1
else:
res.append([left,right])
while lo<hi and nums[lo]==left:
lo += 1
while lo<hi and nums[hi]==right:
hi -= 1
else:
i = start
while i<sz:
old = nums[i]
sub = self.targetSum(nums,n-1,i+1,target-nums[i])
for temp in sub:
temp.append(nums[i])
res.append(temp)
while i<sz and nums[i]==old:
i += 1
return res
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
nums.sort()
return self.targetSum(nums,4,0,target) #只是此处调用的时候指定了target而已
js
/**
* @param {number[]} nums
* @param {number} target
* @return {number[][]}
*/
var fourSum = function(nums, target) {
nums.sort((a,b)=>a-b);
return targetSum(nums,4,0,target);
};
var targetSum = function(nums,n,start,target){
let sz = nums.length;
let res = [];
if(n<2 || n>sz){
return res;
}
if(n==2){
let lo=start,hi = sz-1;
while(lo<hi){
let sum_ = nums[lo]+nums[hi];
let left=nums[lo],right=nums[hi];
if(sum_<target){
while(lo<hi && nums[lo]==left){
lo ++;
}
}else if(sum_>target){
while(lo<hi && nums[hi]==right){
hi --;
}
}else{
res.push([left,right]);
while(lo<hi && nums[lo]==left){
lo ++;
}
while(lo<hi && nums[hi]==right){
hi --;
}
}
}
}else{
let i = start;
while(i<sz){
let old = nums[i]
let sub = targetSum(nums,n-1,i+1,target-nums[i]);
for(let temp of sub){
temp.push(old);
res.push(temp);
}
while(i<sz && nums[i]==old){
i ++;
}
}
}
return res;
}
更多推荐
已为社区贡献2条内容
所有评论(0)