https://leetcode.com/problems/3sum/
给一个数组,要求返回其中所有各不相同的三元组,每个三元组中的三个数相加和为0
O(N2)解法:
本题是Two Sum的进阶版,枚举数组中的数nums[i],然后用O(N)的复杂度在剩下的数中使用Two Sum找到和为-nums[i]的不同组合
先对nums数组进行快速排序(从小到大),开销O(NlogN)
当我们枚举到nums[i]时,使用双指针滑窗,滑窗左端为i+1,右端为n-1,然后将左右两端的值相加,与-nums[i]进行比较
如果和大于-nums[i],则右端向左移,如果和小于-nums[i],则左端向右移,如果和等于-nums[i],则更新当前结果到答案中,然后左右两端同时向内侧移(滑窗两端都需要更新到不同的值才有可能让结果依然相等)
当左右两端相遇后,nums[i]的结果就都考虑完了,i向右移
滑窗的起点从i+1开始而不是从0开始,是因为nums[i]与前面的数所组成的合法三元组,已经在枚举前面的数的时候考虑过了,所以滑窗从i后面开始是正确的
需要注意的是,因为答案要求所有的三元组各不相同,所以上面所有描述的移动操作,都是移动到下一个不同的值,这样就可以保证枚举出的所有结果都是各不相同的
1 class Solution { 2 public: 3 vector<vector<int>> threeSum(vector<int>& nums) { 4 vector<vector<int>> ret; 5 sort(nums.begin(),nums.end()); 6 int n = nums.size(); 7 for (int i = 0; i < n; ) { 8 if (nums[i] > 0) break; 9 int Target = -nums[i]; 10 int low = i + 1, high = n - 1; 11 while (low < high) { 12 if (nums[low] + nums[high] == Target) { 13 int ans[3] = { nums[i] ,nums[low] ,nums[high] }; 14 ret.push_back(vector<int>(ans,ans+3)); 15 16 for (++low; low < n; low++) { 17 if (nums[low] != nums[low - 1]) { 18 break; 19 } 20 } 21 22 for (--high; high >= 0; high--) { 23 if (nums[high] != nums[high + 1]) { 24 break; 25 } 26 } 27 } 28 else if (nums[low] + nums[high] < Target) { 29 for (++low; low < n; low++) { 30 if (nums[low] != nums[low - 1]) { 31 break; 32 } 33 } 34 } 35 else { 36 for (--high; high >= 0; high--) { 37 if (nums[high] != nums[high + 1]) { 38 break; 39 } 40 } 41 } 42 } 43 for (++i; i < n; i++) { 44 if (nums[i] != nums[i - 1]) { 45 break; 46 } 47 } 48 } 49 50 return ret; 51 } 52 };代码