终于做了决定,开始做LeetCode,上来先做了3题都是关于sum的,这三题我认为都是从同一个问题变过来的,很多人都知道一个经典的问题就是给你一个数组a和一个数字tar,问你这个数组中有没有两个数的和等于这个给定的数字tar,显然要用O(N)的方法,这个问题的答案就是先排序,然后定义两个边界l和r,l一开始等于0,r一开始等于n-1,每次把边界指的两个数相加和给定的数tar比较一下,如果比tar小,那么l++,比tar大,那么r--,如果等于那么l++,r--。那么问题来了,为什么a[l]+a[r]<tar的时候,只需要l++就好了,这是这个做法的关键,这是因为当a[l]+a[r]<tar的时候,肯定有a[l]+a[k]<=a[l]+a[r]<tar,k=[l+1,r-1],因为数组是排好序的。同理也可以说明r--的原因。
这样说来的话,可以用O(N)的方法解决数组中是否有2个数的和等于给定一个数的问题,那么三个数只需要枚举一个数a[i],用这个tar减去枚举的这个数,然后再用O(N)的时间判断剩下的数有没有两个数的和等于tar-a[i]。时间复杂度是O(N*N)。
还有一个问题就是判重,实话说判重花了我很多时间。主要就是有两点:
第一,枚举i后,j一定是i+1开始枚举。
第二,对于枚举的i,j,k如果我发现当前枚举的量和上次循环枚举的值是相等的。那么这次直接continue。
3sum的代码如下:
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num) {
int i ,j,k;
int n=num.size();
vector<int>ans;
vector<vector<int> >cl;
sort(num.begin(),num.end());
for(i=0;i<n;i++)
{
if(num[i]==num[i-1]&&i>0)
continue;
for(j=i+1,k=n-1;j<k;)
{
if(num[j]==num[j-1]&&j>i+1)
{
j++;
continue;
}
if(num[k]==num[k+1]&&k<n-1)
{
k--;
continue;
}
if(num[j]+num[k]+num[i]==0)
{
ans.push_back(num[i]);
ans.push_back(num[j]);
ans.push_back(num[k]);
cl.push_back(ans);
ans.clear();
j++;
k--;
}
else if(num[j]+num[k]+num[i]<0)
j++;
else
k--;
}
}
return cl;
}
};
3sumclosest 代码如下:
class Solution {
int abs(int x)
{
return x>0?x:-x;
}
public:
int threeSumClosest(vector<int> &num, int target) {
int n=num.size();
int i,j,k;
sort(num.begin(),num.end());
int min=100000000;
int ans;
for(i=0;i<n;i++)
{
for(j=i+1,k=n-1;j<k;)
{
if(abs(num[i]+num[j]+num[k]-target)<min)
{
min=abs(num[i]+num[j]+num[k]-target);
ans=num[i]+num[j]+num[k];
}
if(num[j]+num[k]+num[i]>target)
k--;
else if(num[j]+num[k]+num[i]<target)
j++;
else
return target;
}
}
return ans;
}
};
class Solution {
public:
vector<vector<int> > fourSum(vector<int> &num, int target) {
int n=num.size();
vector<vector<int> >ans;
int i,k,j,l;
vector<int>tmp;
sort(num.begin(),num.end());
for(i=0;i<n;i++)
{
if(i>0&&num[i]==num[i-1])
continue;
for(j=i+1;j<n;j++)
{
if(j>i+1&&num[j]==num[j-1])
continue;
int sum=target-num[i]-num[j];
for(k=j+1,l=n-1;k<l;)
{
if(k>j+1&&num[k]==num[k-1])
{
k++;
continue;
}
if(l<n-1&&num[l]==num[l+1])
{
l--;
continue;
}
if(num[k]+num[l]==sum)
{
tmp.clear();
tmp.push_back(num[i]);
tmp.push_back(num[j]);
tmp.push_back(num[k]);
tmp.push_back(num[l]);
ans.push_back(tmp);
k++;
l--;
}
else if(num[k]+num[l]<sum)
k++;
else
l--;
}
}
}
return ans;
}
};