本题,与3Sum类似。
只需在3Sum的基础上再加一层循环即可。
总结规律,在网上查询,发现目前比较好的办法就是以最初的2Sum为基础,将kSum逐渐降低k值,直到最终弱化为2Sum。
即:kSum->(k-1)Sum->……->4Sum->3Sum->2Sum.
网上多是直接解决4Sum的解法,其算法思路固然很好,却丧失了程序的灵活性。
本人结合大家的思路,贡献一个采用递归的kSum的程序,可自由设定k值和target。通过leetcode。
优点:可灵活设定K值和target,解决一系列的类似问题
缺点:存储中间结果需要多次的push_back() 和pop_back(),所以速度有点慢,leetcode显示时间为185ms.
主要思路:
假设,K>=2。
采用递归的思想,逐步弱化:kSum->(k-1)Sum->……->4Sum->3Sum->2Sum.
确定递归的最终情况:2Sum。
鉴于leetcode的测试要求,定义一个暂时的vector v,用于存储每一种结果,期间根据需要进行push_back() 和pop_back()。
代码如下:
class Solution {
public:
//希望能够写成Ksum的程序,而不是只是针对4sum的。为此,需要写递归迭代的办法。
void twoSum( vector<int> &num, int dex, vector<vector<int> > &result, vector<int> v, int target)
{
int i=dex;
int j=num.size()-1;
while(i < j)
{
if(num[i]+num[j] > target)
--j;
else if(num[i]+num[j] < target)
++i;
else
{
//找到匹配的,则存入结果
v.push_back(num[i]);
v.push_back(num[j]);
result.push_back(v);
v.pop_back();//及时清除v中最后两个数据,继续向后方扫,寻找匹配值
v.pop_back();
i++;
j--;
//跳过2Sum中的重复值
while(i < num.size() && num[i]==num[i - 1]) i++;
while(j >= 0 && num[j] == num[j + 1]) j--;
}
}
}
void kSum( vector<int> &num, int dex, vector<vector<int> > &result,vector<int> v, int target, int k )
{
if(k > 2)
{
for(int i=dex+1; i < num.size()-1; ++i)
{
v.push_back( num[i-1]);
kSum(num, i, result, v, target-num[i-1], k-1);
v.pop_back();//当前走完,需要跳到下一个i,需要先清除v中最近一个数据
while( i > 0 && num[i] == num[i-1] )//跳过子(k)层的连续相同的数据,则跳过
++i;
}
}
else
twoSum( num, dex, result, v, target);
}
vector<vector<int> > fourSum(vector<int> &num, int target) {
/*
由于leetcode的测试直接给了target,此处没有定义target,但是可以灵活修改target的值,
*/
sort(num.begin(), num.end());//排序
vector<vector<int> > result;//保存最终结果
vector<int> curResult;//保存中间结果
int count = 4;//K值
if(num.size() >= count)
kSum(num, 0, result, curResult, target, count);
return result;
}
};