LeetCode 3Sum
来源:互联网 发布:java websocket.jar 编辑:程序博客网 时间:2024/06/03 20:25
问题网址:https://leetcode.com/problems/3sum/description/
问题描述:
给定一个n个整数的数组S,是否存在S中的元素a,b,c,使得a + b + c = 0? 查找数组中所有唯一的三元组,其总和为零。
注意:解决方案集不能包含重复的三元组。
问题样例:
For example, given array S = [-1, 0, 1, 2, -1, -4],A solution set is:[ [-1, 0, 1], [-1, -1, 2]]
K Sum问题是一个系列,博客 http://tech-wonderland.net/blog/summary-of-ksum-problems.html 总结得比较完整,有兴趣可以去看。
作为初学者,我们用最简洁的思路来说一下这道题怎么解。
暴力解决法是每个人都能想到的,三层for循环,时间复杂度是O(n^3),而且还要处理重复的问题,显然不是题目想要的解法。
那能不能降到O(n^2)?排序算法的时间复杂度为O(nlgn),小于O(n^2),那么我们不妨先对数组排个序。
排序之后,我们就可以对数组用两个指针分别从前后两端向中间扫描了,如果是 2Sum,我们找到两个指针之和为target就OK了,那 3Sum 类似,我们可以先固定一个数,然后找另外两个数之和为第一个数的相反数就可以了。
代码不难,先看了再说。
首先,两数和问题这样做。先对数组中的数进行排序,再设置两个指针,一个指向头,一个指向尾。判断两数和是否等于想要的数,如果是则在结果集添加这个数组;如果小了说明左边指针指向的数小了,因此左指针右移;反之如果大了则右指针左移。
尝试把三数和问题转化为两数和问题:同样先对数组排序,设置三个指针p,q,r,p指针指向第一个数x,则q,r要指向数组中剩余数中的两个,并且指向的两数和为-x,从而转化为两数和问题。对p指向第一个数的情况分析完毕后,不可能再有满足题意且包含x的情况,于是p右移。这样一直分析到p指向数组中倒数第三个数的情况。注意跳过所有重复的情况。
#include <iostream>#include <vector> #include <algorithm>using namespace std;class Solution{public: vector< vector<int> > threeSum(vector<int> &num) { vector<int> numSet(3); vector< vector<int> > r; // 1.排序 sort(num.begin(), num.end()); int sum; int len = num.size(); // 2.拿出第一个数,转化为两数和问题。注意外层循环到倒数第三个数即可 for(int i = 0; i < len-2; i++) { sum = 0 - num[i]; numSet[0] = num[i]; // 3.两数和问题 for(int j = i+1, k = len-1; j < k;) { if(num[j] + num[k] == sum) { numSet[1] = num[j++]; numSet[2] = num[k--]; r.push_back(numSet); // 根据题目要求,跳过重复元素 while(j < k && num[j] == num[j-1]) j++; while(j < k && num[k] == num[k+1]) k--; } else if(num[j] + num[k] < sum) j++; else k--; } while(i < len-2 && num[i+1] == num[i]) i++; } return r; }};int main() { int a[] = {-2, 13, -5, -4, -7, 8, 0, -9, 6, 7, 0, -4, 2, 1, -2, 4}; int len = sizeof(a) / sizeof(a[0]); vector<int> num(a, a+len); Solution s; vector< vector<int> > result; result = s.threeSum(num); // 输出结果 for(int q = 0; q < result.size(); q++) { vector<int> x = result[q]; cout << "("; int t; for(t = 0; t < x.size()-1; t++) { cout << x[t] << " "; } cout << x[t]; cout << ")" << endl; } return 0;}
public class Solution { List<List<Integer>> ret = new ArrayList<List<Integer>>(); public List<List<Integer>> threeSum(int[] num) { if (num == null || num.length < 3) return ret; Arrays.sort(num); int len = num.length; for (int i = 0; i < len-2; i++) { if (i > 0 && num[i] == num[i-1]) continue; find(num, i+1, len-1, num[i]); //寻找两个数与num[i]的和为0 } return ret; } public void find(int[] num, int begin, int end, int target) { int l = begin, r = end; while (l < r) { if (num[l] + num[r] + target == 0) { List<Integer> ans = new ArrayList<Integer>(); ans.add(target); ans.add(num[l]); ans.add(num[r]); ret.add(ans); //放入结果集中 while (l < r && num[l] == num[l+1]) l++; while (l < r && num[r] == num[r-1]) r--; l++; r--; } else if (num[l] + num[r] + target < 0) { l++; } else { r--; } } } }
- 【Leetcode】3Sum (Sum)
- Leetcode:2Sum,3Sum
- 【Leetcode】3Sum Closest (Sum)
- leetcode 2 sum 3sum 4sum
- Leetcode 2SUM-3SUM-4SUM
- Leetcode-2sum,3sum,4sum
- leetcode 2 sum & 3 sum & 4 sum
- [LeetCode] 2Sum, 3Sum, 4Sum, 3SUm closet
- [LeetCode] K sum(2Sum、3Sum、4Sum)
- leetcode--sum集合:2sum,3sum,4sum
- leetcode --- 2 sum , 3 sum , 4 sum , k sum problem
- LeetCode: 3Sum
- LeetCode: 3 Sum Closest
- leetcode - 3 Sum
- leetcode - 3 sum closest
- leetcode 3Sum
- leetcode 3Sum Closest
- LeetCode: 3Sum
- 学习Linux的基础知识
- 发送邮件
- 【Scikit-Learn 中文文档】43 使用 scikit-learn 介绍机器学习
- html头部
- 在windows中安装tensorflow
- LeetCode 3Sum
- Sublime编辑器指南
- 使用VMware在输入模式下遇到的问题
- 三字棋的实现
- 类加载器
- UNITY_渲染基础
- 【tensorflow_error】'module' has no attribute 'select'
- 剑指offer---二叉树的镜像
- 企信通短信接口(java)