问题
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
- Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
- The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4}, A solution set is: (-1, 0, 1) (-1, -1, 2)
代码
struct node{
int index;
int value;
};
bool compile(const struct node &a , const struct node &b)
{
return a.value < b.value;
}
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num) {
vector<vector<int> > resultv;
int len = num.size();
vector<struct node> temp(len);
struct node n;
for (int i = 0 ; i < len ; i ++) {
n.index = i+1; n.value = num[i];
temp[i] = n;
}
sort(temp.begin() , temp.end() , compile);
int i = 0;
for ( i = 0 ; i < len ; i++) {
int target = 0 - temp[i].value;
//cout<<target<<","<<temp[i].value<<endl;
int j =0;
int k =0;
for (j = i+1 ,k = len-1; j < k; ) {
if (j == i) {
j++;
continue;
}
if (k == i) {
k--;
continue;
}
//cout<<"sum:"<<temp[j].value << "+ "<< temp[k].value<<endl;
if (temp[j].value + temp[k].value < target) {
j++;
}
else if(temp[j].value + temp[k].value > target)
{
k--;
}
else
{
/* equal */
vector<int> group;
group.push_back(temp[i].value);
group.push_back(temp[j].value);
group.push_back(temp[k].value);
resultv.push_back(group);
int tempk = temp[k].value;
int tempi = temp[i].value;
int tempj = temp[j].value;
while (tempk == temp[k].value && k > j) {
k--;
}
while (tempj == temp[j].value && j < k) {
j++;
}
while (tempi == temp[i].value && i< len) {
i++;
}
i--;
//break;
}
}
}
return resultv;
}
};
分析
首先先排序,复杂度O(nlogn);
其次 遍历整个数组,每次确定一个数,假设为a,则其他两个数的和是 ( 0-a) ,(O(N))
再次,按照2sum 的算法找到 (0-a), O(N).
最后,跳过重复的元素。总的复杂度是 O(O^2) + O(NLOGN) = O(N^2)
分析2:
这里还有第二种解法:
1. hash表,i,j遍历一遍,算出所有两两相加的值,并存到hash表中,时间复杂度是O(N^2),控件复杂度也是 n^2。
2. 遍历一遍,利用hash表查找 (0-a) 是否存在,复杂度是 O(N^2) , 和上面一样,不过有些空间上的损失。
这里可以思考得出一个结论,hash表这种算法,可以导出 4sum 的算法复杂度也可以是 O(N^2)。下一篇博文将实现这个算法。
总结
2sum的一种变形。