【LeetCode】15_3Sum
来源:互联网 发布:windows图形编程 高清 编辑:程序博客网 时间:2024/06/12 01:38
题目
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)
解析
其实就是另一个版本的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; }
- 【LeetCode】15_3Sum
- LeetCode 15_3Sum
- LeetCode之15_3Sum
- leetcode第一刷_3Sum
- 【LeetCode】16_3Sum Closest
- LeetCode 16_3Sum Closest
- leetcode第一刷_3Sum Closest
- LeetCode之16_3Sum Closest
- 0016_3Sum Closest
- leetcode15&16_3Sum&4Sum
- leetcode-15
- Leetcode 15
- LeetCode 15
- Leetcode(15)
- leetcode 15
- LeetCode 15
- Leetcode 15 3Sum
- LeetCode 15: 3Sum
- 模板方法模式
- java面试中长被问到的细节
- android客户端提交的数据怎么插入到远程服务器数据库
- 类的封装和访问控制
- Android软件安全与逆向分析-笔记(1)
- 【LeetCode】15_3Sum
- Struts2中关于"There is no Action mapped for namespace / and action name"的总结
- Java遍历文件夹的两种方法(非递归和递归) .
- OC协议应用之代理者模式
- JavaSE之内部类
- 老罗安卓教程 在TextView文本中跳转到Activity
- 6.代理模式(设计模式笔记)
- Linux 下Sqlite3 的安装及应用
- C++ 虚函数表解析