给定一个数组,求出和为0的所有三元组

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

转载于:https://www.cnblogs.com/ZJUKasuosuo/archive/2012/08/10/2632039.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值