【LeetCode】15_3Sum

来源:互联网 发布:windows图形编程 高清 编辑:程序博客网 时间:2024/06/12 01:38

题目

Given an array S of n integers, are there elements abc 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)

解析

其实就是另一个版本的2 sum。先排序,固定住第一个数字i,从后面的数字中去寻找和为-i的就可以了。需要注意的是:排序后的数字可能重复的很多,但是不可以去掉重复的,比如6,-3,-3这种组合,如果去掉重复数字就会出问题。

减少重复的几个环节是:

1.假设我们固定了数字i,那么只需要从i后面去查找剩下的数字就好了。前面的数字找到的肯定是重复的。

2.需要考虑连续几个数字都相等的情况。i+1和i的数字相等,那么直接跳过相等的。

3.即使这样还是可能有重复的,这个时候再用vector去重复。

我的代码如下:

//LeetCode 15vector<vector<int>> threeSum_15(vector<int>& nums) {sort(nums.begin(),nums.end());vector<vector<int>> ret;if (nums.size() < 3) return ret;for (int i = 0;i<nums.size();i++){if (i>0 && nums.at(i)==nums.at(i-1)){continue;}int target = nums.at(i);int j = i+1;int k = nums.size()-1;while (j < k){if (nums.at(j)+nums.at(k)+target == 0){vector<int> tmp;tmp.push_back(target);tmp.push_back(nums.at(j));tmp.push_back(nums.at(k));ret.push_back(tmp);j++;}else if (nums.at(j)+nums.at(k)+target > 0){k--;}else{j++;}}}vector<vector<int>>::iterator iter;iter = unique(ret.begin(),ret.end());if(iter != ret.end()){ret.erase(iter,ret.end());}return ret;

1.第一个知识点是迭代器

vector <int>::iterator Iter; for ( Iter = v1.begin( ) ; Iter != v1.end( ) ; Iter++ )      cout << " " << *Iter;   cout << endl;

2.另一个知识点是如何抹除数据

 v1.erase( v1.begin( ) );v1.erase( v1.begin( ) + 1, v1.begin( ) + 3 );

3.最后去掉重复数据

vector<vector<int>>::iterator iter;iter = unique(ret.begin(),ret.end());if(iter != ret.end()){  ret.erase(iter,ret.end());}

我们都知道unique的功能是去除相邻的重复元素(只保留一个),还有一个容易忽视的特性是它并不真正把重复的元素删除,不知道这个特性用起来就会出问题。unique只是把重复的元素放到容器的后面,而它本身会返回一个迭代器,只向这些元素的开始部分。因此要向真正删除这些元素,还是要“手工”处理一下。对于上面的例子,可以用vector窗口的erase.


代码可以通过,但是耗时120ms,属于耗时很多的人群。


来看看大神们的版本。

因为我们固定了i的值,例如-3,后面出现-3,6。表面上看有两个-3,似乎不能跳过这些-3.但其实第一个-3是固定的,没有参与后面的搜索,所以其实是应该跳过重复的值,这样就不会出现重复的vector了。

代码如下

vector<vector<int>> threeSum(vector<int>& num) {  vector<vector<int>> result;  if (num.size() < 3) return result;  sort(num.begin(), num.end());  const int target = 0;  auto last = num.end();  for (auto i = num.begin(); i < last-2; ++i) {    auto j = i+1;    if (i > num.begin() && *i == *(i-1)) continue;    auto k = last-1;    while (j < k) {      if (*i + *j + *k < target) {      ++j;     while(*j == *(j - 1) && j < k) ++j;    } else if (*i + *j + *k > target) {      --k;      while(*k == *(k + 1) && j < k) --k;    } else {    result.push_back({ *i, *j, *k });     ++j;     --k;     while(*j == *(j - 1) && *k == *(k + 1) && j < k) ++j;    }   }  }return result;}

在大神代码的启发下,我重改了一下,速度还可以。

    vector<vector<int>> threeSum(vector<int>& nums) {       sort(nums.begin(),nums.end());vector<vector<int>> ret;if (nums.size() < 3) return ret;for (int i = 0;i<nums.size();i++){if (i>0 && nums.at(i)==nums.at(i-1)){continue;}int target = nums.at(i);int j = i+1;int k = nums.size()-1;while (j < k){if (nums.at(j)+nums.at(k)+target == 0){vector<int> tmp;tmp.push_back(target);tmp.push_back(nums.at(j));tmp.push_back(nums.at(k));ret.push_back(tmp);j++;k--;while (j<k && nums.at(k)==nums.at(k+1))k--;while (j<k && nums.at(j)==nums.at(j-1))j++;}else if (nums.at(j)+nums.at(k)+target > 0){        k--;while (j<k && nums.at(k)==nums.at(k+1))k--;}else{  j++;while (j<k && nums.at(j)==nums.at(j-1))  j++;}}}return ret;    }











0 0
原创粉丝点击