3 Sum
http://www.lintcode.com/en/problem/3sum/
Discussion
先排序,后夹逼,注意消除结果里面的重复三元组。 复杂度$$O(n^2)$$
Solution
class Solution {
public:
/**
* @param numbers : Give an array numbers of n integer
* @return : Find all unique triplets in the array which gives the sum of zero.
*/
vector<vector<int> > threeSum(vector<int> &nums) {
// write your code here
vector<vector<int> > result;
if (nums.size() < 3) return result;
sort(nums.begin(), nums.end());
for(vector<int>::iterator it = nums.begin(); it<nums.end()-2; it++) {
vector<int>::iterator ita = it+1;
vector<int>::iterator itb = nums.end()-1;
while(ita < itb) {
if(*it + *ita + *itb == 0) {
result.push_back({*it , *ita , *itb});
ita++;
itb--;
} else if(*it + *ita + *itb < 0) {
ita++;
} else {
itb--;
}
}
}
sort(result.begin(), result.end());
vector<vector<int> >::iterator it = unique(result.begin(), result.end());
result.resize(it-result.begin());
return result;
}
};
- 要习惯用iterator遍历,方便,当然用下标也可以。
- 结果是有可能存在重复元素的,比如输入[1,0,-1,-1,-1,-1,0,1,1,1], 会返回好多[-1,0,1]
- 去除vector里的重复元素的方法,先sort,再用unique返回the element that follows the last element not removed. 需要注意的是unique是不会改变vector的size的,需要调用resize或者erase函数。
sort(result.begin(), result.end()); vector<vector<int> >::iterator it = unique(result.begin(), result.end()); result.resize(it-result.begin());//or result.resize(distance(result.begin(), it)) // or result.erase(it, result.end());
- 如果在遍历vector的元素就去除元素会更简单。注意要跳过第一个元素重复的情况,和记录重复的情况。as follows:
class Solution { public: /** * @param numbers : Give an array numbers of n integer * @return : Find all unique triplets in the array which gives the sum of zero. */ vector<vector<int> > threeSum(vector<int> &nums) { // write your code here vector<vector<int> > result; vector<int> lastrecord; if (nums.size() < 3) return result; sort(nums.begin(), nums.end()); for(vector<int>::iterator it = nums.begin(); it<nums.end()-2; it++) { vector<int>::iterator ita = it+1; vector<int>::iterator itb = nums.end()-1; if(it>nums.begin() && *it == *(it-1)) continue;//第一个元素重复,说明已经遍历过了,跳过 while(ita < itb) { if(*it + *ita + *itb == 0) { vector<int> record = {*it , *ita , *itb}; if(lastrecord != record) { result.push_back(record); lastrecord = record; }//给定第一个元素,第二三个元素也有可能重复,所以用lastrecord保存上一条记录。 ita++; itb--; } else if(*it + *ita + *itb < 0) { ita++; } else { itb--; } } } return result; } };
更简洁的写法:
class Solution {
public:
/**
* @param numbers : Give an array numbers of n integer
* @return : Find all unique triplets in the array which gives the sum of zero.
*/
vector<vector<int> > threeSum(vector<int> &nums) {
vector<vector<int> > result;
if(nums.empty()) return result;
sort(nums.begin(), nums.end());
for(auto it = nums.begin(); it<nums.end()-2; it++) {
//skip duplicates
if(it != nums.begin() && *(it) == *(it-1)) continue;
auto ita = it+1;
auto itb = nums.end() - 1;
while(ita < itb) {
//skipt duplicates
if(distance(it, ita) > 1 && *ita == *(ita-1)) {ita++; continue;}
if(distance(itb, nums.end()) > 1 && *itb == *(itb+1)) {itb--; continue;}
if(*ita + *itb > -(*it)) {
itb--;
} else if(*ita + *itb < -(*it)) {
ita++;
} else {
result.emplace_back(vector<int>{*it, *ita, *itb});
ita++;
itb--;
}
}
}
return result;
}
};