LeetCode 15: 3Sum
来源:互联网 发布:js控制input显示隐藏 编辑:程序博客网 时间:2024/05/21 08:36
3Sum[1]
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)。
解题思路
思路一:使用3层 for 循环,穷举所有符合条件的三元组(non-descending order)。由于原始输入数组本身可能包含重复元素,所以需要对选取到的三元组进行筛选移除重复三元组 。时间复杂度O(N3),代码如下:
class Solution {public: vector<vector<int>> threeSum(vector<int>& nums) { int numsLen = nums.size(); vector<vector<int>> ret; for (int i = 0; i < numsLen; ++i) { for (int j = i + 1; j < numsLen; ++j) { for (int k = j + 1; k < numsLen; ++k) { // 3层 for 循环,穷举所有符合条件的三元组 if (nums[i] + nums[j] + nums[k] == 0) { vector<int> triplet({nums[i], nums[j], nums[k]}); // non-descending order sort(triplet.begin(), triplet.end()); ret.push_back(triplet); } } } } // 对选取到的三元组进行筛选移除重复三元组 sort(ret.begin(), ret.end(), less<vector<int>>()); vector<vector<int> >::iterator new_end = unique(ret.begin(), ret.end()); ret.erase(new_end, ret.end()); return ret; }};
思路二:可以对上述暴力解法做一些改进。题目要求选出的三元组是非递减的,所以先对输入数组进行排序;依然使用3层 for 循环,穷举所有符合条件的三元组(non-descending order);因为数组已经有序,很容易在获取符合条件的三元组时就进行去重,而不用在求出所有的三元组之后再进行一次排序进行去重。时间复杂度依然是O(N3)。代码如下:
class Solution { public: vector<vector<int> > threeSum(vector<int> &num) { // 为了选出的三元组是非递减的,先对输入数组进行排序 sort(num.begin(), num.end()); vector<int> triplet; vector<vector<int> > result; size_t size = num.size(); // 3层 for 循环,穷举所有符合条件的三元组 for (size_t i = 0; i < size; i++) { // 如果第一个元素已经大于目标0,则直接返回 if (num[i] > 0) { break; } // 去重,如果当前第一个元素与上一次的第一个元素相同,则跳过该元素 if (i > 0 && num[i] == num[i-1]) { continue; } for (size_t j = i + 1; j < size; j++) { // 去重,如果当前第二个元素与上一次的第二个元素相同,则跳过该元素 // 限制的是符合条件的三元组中的第二个元素,这里需要判断j>i+1,以避免与第一个元素比较 if (j > i+1 && num[j] == num[j-1]) { continue; } for (size_t k = j + 1; k < size; k++) { // 去重,原理与上同 if (k > j+1 && num[k] == num[k-1]) { continue; } // 这里的符合条件的三元组已经经过了所有的去重处理,是最终结果中的一个 if (num[i] + num[j] + num[k] == 0) { triplet.push_back(num[i]); triplet.push_back(num[j]); triplet.push_back(num[k]); result.push_back(triplet); triplet.clear(); } } } } return result; } };
思路三:首先对数组进行排序。对于3Sum问题,我们可以先固定第一个数;然后找另外两个数之和为第一个数的相反数,这是一个2Sum,可以使用两个指针分别从数组的前后两端向中间扫描。因为数组是有序的,因此对于 num[i],寻找另外两个数时,只要从 i+1 开始找就可以了。时间复杂度为O(N2)。
代码如下:
class Solution { public: vector<vector<int> > threeSum(vector<int> &nums) { int numsLen = nums.size(); vector<int> triplet; vector<vector<int>> result; // 对数组排序 sort(nums.begin(), nums.end()); // 先固定第一个数;然后找另外两个数之和为第一个数的相反数 for (int i = 0; i < numsLen; ++i) { // 第一个数去重 if (i > 0 && nums[i] == nums[i-1]) { continue; } // 使用两个指针分别从数组的 i+1 和 numsLen-1 两端向中间扫描,解决2Sum问题 int left = i + 1; int right = numsLen - 1; while (left < right) { if (nums[left] + nums[right] == -nums[i]) { triplet.push_back(nums[i]); triplet.push_back(nums[left]); triplet.push_back(nums[right]); result.push_back(triplet); triplet.clear(); left++, right--; // 第二个数去重 while (nums[left-1] == nums[left]) left++; // 第三个数去重 while (nums[right] == nums[right+1]) right--; } else if (nums[left] + nums[right] < -nums[i]) { left++; } else { right--; } } } return result; } };
- 关于该问题更详细的介绍请参考维基百科3SUM词条 ↩
0 0
- Leetcode 15 3Sum
- LeetCode 15: 3Sum
- leetcode 15 3Sum
- [leetcode 15] 3Sum
- Leetcode【15】:3Sum
- [leetcode 15] 3Sum
- [Leetcode] 15 - 3Sum
- leetcode.15-----------3Sum
- leetcode 15 3Sum
- leetcode-15 3Sum
- 3Sum - LeetCode 15
- Leetcode #15 3 Sum
- LeetCode---(15) 3 sum
- LeetCode 15 - 3Sum
- leetcode-15 3sum
- leetcode 15 -- 3Sum
- Leetcode[15]-3Sum
- LeetCode 15: 3 Sum
- 一款很好用的图片集左右滚动代码,可修改滚动宽度,总宽度,速度等
- Oracle 11g用exp无法导出空表的处理发布方法
- Python及第三方库api查看
- STM32F103UCOSii笔记
- "undefined reference to" 问题解决方法
- LeetCode 15: 3Sum
- 数学还勉强管用,用代码还能画个canvas 仪表盘(含完整代码)
- Cocos2d-x3.2与OpenGL渲染总结(一)Cocos2d-x3.2的渲染流程
- Thinkphp——关于前台显示栏目和限制显示对应栏目下的商品或文章列表的数目
- Spring MVC过滤器-登录过滤
- http://www.javaapk.com
- 开发中的一些小细节
- linux mount (挂载命令)详解
- webstorm+Cocos2d-js