15. 3Sum

  • Total Accepted: 131800
  • Total Submissions: 675028
  • Difficulty: Medium

  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: 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]
] 思路:
  首先说点题外话,对于2Sum,3Sum,以及后面的4Sum,kSum等是一个系列的,具体的讨论在这篇文章中有提到,大家感兴趣的可以看看:http://www.sigmainfy.com/blog/summary-of-ksum-problems.html
  回到正文,这道题很容易想到的是暴力解法,这也是我们通常采用的办法,但是这样的方法的复杂度是O(n3),再加上去重的复杂度,这样的代码在leetcode是无法成功运行的。

  对于简化的思路,我自己没有想出来,网上参考的是:【LeetCode】3Sum 解题报告

  我们不妨先对数组排个序。排序之后,我们就可以对数组用两个指针分别从前后两端向中间扫描了,如果是 2Sum,我们找到两个指针之和为target就OK了,那 3Sum 类似,我们可以先固定一个数,然后找另外两个数之和为第一个数的相反数就可以了。代码不难,先看了再说。

 public class No_015 {
/*
* 方法一:暴力解法
*/
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<List<Integer>>() ;
if(nums == null || nums.length < 3){
return res ;
}
List<Integer> list = null ;
for(int i = 0 ; i < nums.length-2 ; i++){
for(int j = i+1 ; j < nums.length-1 ; j++){
for(int k = j+1 ; k < nums.length ; k++){
if((nums[i] + nums[j] + nums[k]) == 0){
list = toRange(nums,i,j,k) ;
if(!isContain(res,list)){
res.add(list) ;
}
}
}
}
}
return res ;
} /*
* 对三个数之和为0的数加入list的时候进行排序,方便后面去重
*
* 唉,怎么没想到一开始就对曾格格数组进行排序呢???
*/
private List<Integer> toRange(int [] nums ,int i , int j , int k){
List<Integer> list = new ArrayList<Integer>() ;
int max = nums[i]>nums[j]?nums[i]:nums[j] ;
int min = nums[i]+nums[j]-max ;
max = max>nums[k]?max:nums[k] ;
min = min<nums[k]?min:nums[k] ;
list.add(min) ;
list.add(nums[i]+nums[j]+nums[k]-max-min) ;
list.add(max) ;
return list ;
}
/*
* 检查是否有重复
*/
private boolean isContain(List<List<Integer>> res , List<Integer> list){
if(res == null || res.size() == 0){
return false ;
}
for(List<Integer> each:res){
if(each.get(0) == list.get(0) && each.get(1) == list.get(1)){
return true ;
}
}
return false ;
} /*
* 方法二:首先进行排序,然后根据排序之后的数组,从两边到中间的办法查询,这样复杂度为o(n^2)
*/
List<List<Integer>> ret = new ArrayList<List<Integer>>();
public List<List<Integer>> threeSum2(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--;
}
}
} }
 

最新文章

  1. MySQL----This version of MySQL doesn&#39;t yet support &#39;LIMIT &amp; IN/ALL/ANY/SOME subquery
  2. 第七周——Linux内核如何装载和启动一个可执行程序
  3. 解读JSP的解析过程
  4. Python 抓取网页乱码问题 以及EXCEL乱码
  5. Java基础知识强化之IO流笔记43:IO流练习之 复制文本文件的 5 种方式案例
  6. Linux - PCB之task_struct结构体
  7. (基础篇 走进javaNIO)第二章-NIO入门
  8. Spring boot 国际化自动加载资源文件问题
  9. ESB开发WebService接口
  10. SQL Server 远程备份详解
  11. 抓包神器 tcpdump 使用介绍
  12. 计算2个时间之间经过多少Ticks
  13. 超全PHP学习资源整理:入门到进阶系列
  14. windows可以使用curl啦(以及其他的Linux下面的指令)!
  15. HDU 1875 畅通工程再续 最小生成树问题
  16. C++ 第一课:预处理命令
  17. 10种canvas鼠标光标动画特效
  18. Ecliplse转IDEA的学习思路
  19. Java面向对象-Java类的继承及super关键字
  20. vs2010远程调试断点无效问题

热门文章

  1. HBase with MapReduce (SummaryToFile)
  2. poj3660 floyd
  3. CSS行内元素和块级元素的居中
  4. H.264 / MPEG-4 Part 10 White Paper-翻译
  5. 使用HelloCharts绘制柱状图
  6. 【LeetCode OJ】Flatten Binary Tree to Linked List
  7. iar 错误解决
  8. sqlserver OpenRowSet 对应的三种数据库驱动
  9. Linux压缩那些事儿
  10. oracle 存储过程的写法