如果说只是n的三次方,方法和上题一样的话,那么这题也什么太大意思,下面的方法就是n的三次方,也通过了。不过不知道有没有更好的。
// LeetCode_4Sum.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
vector<vector<int> > fourSum(vector<int> &num, int target) {
int lennum = num.size();
vector<vector<int> > ret;
vector<int> rettemp;
if (lennum<4)
return ret;
sort(num.begin(),num.end());
bool *flag = new bool[lennum];
memset(flag,false,lennum);
for (int i=0;i<lennum;i++)
{
flag[i] = true;
for (int j=i+1;j<lennum;j++)
{
flag[j] = true;
int targettemp = target - num[i] - num[j];
int start=0,end=lennum-1;
while(start<end&&flag[start]==true)
start++;
while(start<end&&flag[end]==true)
end--;
while(start<end)
{
if (num[start]+num[end]==targettemp)
{
rettemp.push_back(num[i]);
rettemp.push_back(num[j]);
rettemp.push_back(num[start]);
rettemp.push_back(num[end]);
sort(rettemp.begin(),rettemp.end());
ret.push_back(rettemp);
rettemp.clear();
start++;
while(start<end&&flag[start]==true)
start++;
end--;
while(start<end&&flag[end]==true)
end--;
}
else
{
if (num[start]+num[end]<targettemp)
{
start++;
while(start<end&&flag[start]==true)
start++;
}
else
{
end--;
while(start<end&&flag[end]==true)
end--;
}
}
}
flag[j] = false;
}
flag[i] = false;
}
sort(ret.begin(),ret.end());
ret.erase(unique(ret.begin(),ret.end()),ret.end());
return ret;
}
int _tmain(int argc, _TCHAR* argv[])
{
vector<int> vec;
vec.push_back(-1);//{-1 0 1 2 -1 -4}
vec.push_back(0);
//vec.push_back(0);
//vec.push_back(0);
vec.push_back(0);
vec.push_back(1);
vec.push_back(2);
vec.push_back(-2);
vec.push_back(-4);
vector<vector<int> > ret;
ret = fourSum(vec,0);
int retlen = ret.size();
for (int i=0;i<retlen;i++)
{
for(int j=0;j<ret[i].size();j++)
cout<<ret[i][j]<<" ";
cout<<endl;
}
system("pause");
return 0;
}
有人说时间复杂度O(n^2)的方法,空间复杂度为O(n)的解法:采用分治思想,先对数组预处理,求的元素两两之和,然后采用2Sum算法思想遍历数组求的四个数字之和。
我的理解是:求两两元素之和后,数据就已经增大的一个数量级,既是后来采用的O(n)的方法相当于O(n的平方),之后还要进行排序,时间为n方*log(n),在遍历选择两个数和的时候还要考虑原来的元素要来自不同的元素(一个值只能用一次),最坏情况下为O(n方),所以这种方法最坏情况还是为n的四次方。加之要考虑后来的和所来自的元素复杂度不少。