一个数组,找出所有3个数加起来等于0的组合。不要重复的组合,并且按递增顺序输出结果。
思路:先对数组进行一次快排。然后从最小的数开始,找到所有其后面的另外2个数与其和为0。3个数的和为0,确定了其中的一个,就是要找到另外的nums[m]+nums[n]=-nums[i]的数,由于一次循环中就已经找到了所有的m,n,因而相同的nums[i]就不必再考虑了。另外,对于求m,n的方法,其中一个确定,另一个就确定了,所以相同的nums[m]和nums[n]也不用再考虑。事实上nums[m]可以等于nums[n],但是对于确定的nums[i],nums[m]!=nums[m-1]。
#include<iostream> #include<vector> using namespace std; class Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { vector<vector<int>> results; vector<int> triblets(3,0); nums.insert(nums.begin(),0); QSort(nums,1,nums.size()-1); for(int i=1;i<nums.size()-1;i++) { if(i>=2&&nums[i]==nums[i-1]) continue; //下面的代码已经找到了和等于-nums[i]的所有数对,因而和前面相同的数就不用考虑了 int m=i+1; int n=nums.size()-1; while(m<n) { if(m>i+1&&nums[m]==nums[m-1]){ //对于和确定的数,一个数确定了另一个数也就定了。所以nums[m]/nums[n]不变的值都不用考虑 m++;continue; } if(n<nums.size()-1&&nums[n]==nums[n+1]){ n--;continue; } if(nums[m]+nums[n]==-nums[i]) { triblets[0]=nums[i]; triblets[1]=nums[m]; triblets[2]=nums[n]; results.push_back(triblets); m++;n--; } else if(nums[m]+nums[n]>-nums[i]) { n--; } else { m++; } } } return results; } private: int Partition(vector<int>& L,int low,int high) { L[0]=L[low]; //L[0]号位置是没有用的,用来存储枢纽值 while(low<high) { while(low<high&&L[high]>=L[0]) --high; //比哨兵位置大的值就不变,把high往前移 L[low]=L[high]; while(low<high&&L[low]<=L[0]) ++low; //比哨兵大的值才往后面移动,保证了所有小于等于哨兵的值都在哨兵的前面。 L[high]=L[low]; } //到此为止,low一定是等于high的 L[low]=L[0]; //再把L[0]处的值还原到L[low] return low; } void QSort(vector<int>& L,int low,int high) { if(low<high) { int pivotloc=Partition(L,low,high); QSort(L,low,pivotloc-1); QSort(L,pivotloc+1,high); } } };