1. 题目:给定一个数组求出和为0的所有三元组,要求去除重复的情况,如[-1,0,1]和[0,-1,1]是相同的情况。
2. 分析:有一道经典题目是:给定一个有序数组,求出和为0的所有二元组。这道题目通过两个指针,一个从前向后走,一个从后向前走。最终的时间复杂度为O(n)。本题是这道题目的变形或者说引申。最原始的算法:三重for循环,找出所有情况,时间复杂度为O(n^3)。不过,根据上面那道题目可以得到一个时间复杂度为O(n^2)的算法。要求a+b+c=0,可以变成a+b=-c这种形式,外循环遍历一次数组,相当于固定c,内循环判断a+b是否等于-c。
3. 代码:
View Code
1 #include <iostream> 2 #include <cassert> 3 #include <set> 4 #include <vector> 5 #include <algorithm> 6 using namespace std; 7 8 set<vector<int> > find_triplets(vector<int> arr) { 9 sort(arr.begin(), arr.end()); 10 set<vector<int> > triplets; 11 vector<int> triplet(3); 12 int n = arr.size(); 13 for (int i = 0;i < n; i++) { 14 int j = i + 1; 15 int k = n - 1; 16 while (j < k) { 17 int sum_two = arr[i] + arr[j]; 18 if (sum_two + arr[k] < 0) { 19 j++; 20 } else if (sum_two + arr[k] > 0) { 21 k--; 22 } else { 23 triplet[0] = arr[i]; 24 triplet[1] = arr[j]; 25 triplet[2] = arr[k]; 26 triplets.insert(triplet); 27 j++; 28 k--; 29 } 30 } 31 } 32 return triplets; 33 } 34 35 int main() 36 { 37 enum{aLength=15}; 38 int a[aLength]={-4,-2,-2,-2,0,1,2,2,2,3,3,4,4,6,6}; 39 vector<int> vec(a,a+aLength-1); 40 set<vector<int> > se=find_triplets(vec); 41 set<vector<int> >::iterator iter=se.begin(); 42 while (iter!=se.end()) 43 { 44 for (int i=0;i<(*iter).size();i++) 45 { 46 cout<<(*iter)[i]<<" "; 47 } 48 cout<<endl; 49 iter++; 50 } 51 return 0; 52 }
4. 一些新的题目可以从已经熟悉的题目中得到启发。
5. 运行结果:
6. 参考文章:
http://www.leetcode.com/2010/04/finding-all-unique-triplets-that-sums.html