一、回顾2sum
上次有道题是找两个数的和等于目标数,这道题后来在编程之美上看到过,有另外一种解法为
<pre name="code" class="cpp">for(int m=0,n=num.size()-1;m<n;)
{
if(target==num[m]+num[n])
{
vector<int> tmp;
tmp.push_back(num[i]);
tmp.push_back(num[m]);
tmp.push_back(num[n]);
res.push_back(tmp);break;
}
else
{
if(target>num[m]+num[n])
{
m++;
}else
{
n--;
}
}
}
排序的时间复杂度为O(NlgN),后面的时间复杂度为O(N)
二3sum时间复杂度为O(N2)的解法
题目为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.
第一眼看到这个的时候,我想到的是先排序,然后想到能否利用上面的解法,这是可以的,直接上代码吧
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num) {
vector<vector<int>> res;
int N=num.size();
if(N<3)
return res;
sort(num.begin(),num.end());
for(int i=0;i<N-2;i++)
{
int target=-num[i];
for(int m=i+1,n=N-1;m<n;)
{
if(target==num[m]+num[n])
{
vector<int> tmp;
tmp.push_back(num[i]);
tmp.push_back(num[m]);
tmp.push_back(num[n]);
res.push_back(tmp);
break;
}
else
{
if(target>num[m]+num[n])
{
m++;
}
else
{
n--;
}
}
}
}
if(res.size()>0)
{
while(1)
{
int j=0,siz=res.size();
for(;j<siz-1;j++)
{
if(res[j][0]==res[j+1][0]&res[j][1]==res[j+1][1]&res[j][2]==res[j+1][2])
{
res.erase(res.begin()+j);
break;
}
}
if(j==siz-1)
break;
}
}
return res;
}
};
这种方法在leetcode上提交不上去,超时了,应该有更简单的算法
三、O(N2)算法的改进
可以不用另外检查重复,如果相邻的两个数相同的话,可以直接跳过去,看代码吧
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num) {
vector<vector<int>> res;
int N=num.size();
if(N<3)
return res;
sort(num.begin(),num.end());
for(int i=0;i<N-2;i++)
{
if(i&&num[i]==num[i-1])
continue;
int target=-num[i];
for(int m=i+1,n=N-1;m<n;)
{
if(m-i-1&&num[m]==num[m-1])
{
m++;
continue;
}
if(target==num[m]+num[n])
{
vector<int> tmp;
tmp.push_back(num[i]);
tmp.push_back(num[m]);
tmp.push_back(num[n]);
res.push_back(tmp);
m++;
}
else
{
if(target>num[m]+num[n])
{
m++;
}
else
{
n--;
}
}
}
}
return res;
}
};
当把这个查改了之后,立马就accepted,那么肯定是查重的问题了。我对这个还有点疑惑。