终于做了决定,开始做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; } };