《LeetBook》leetcode题解(15):3Sum[M]
我现在在做一个叫《leetbook》的免费开源书项目,力求提供最易懂的中文思路,目前把解题思路都同步更新到gitbook上了,需要的同学可以去看看
书的地址:https://hk029.gitbooks.io/leetbook/
015. 3Sum
问题
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的变种问题,和这个问题类似的还有4SUM,解题思路也可以参考2SUM。我们知道2SUM还可以用暴力两重循环解决,3SUM如果暴力就要三重循环,想想也可怕。
考虑一下如何将3SUM问题转变一下:如果我们随机确定了一个数a,问题是不是就变成了,在剩下的数里面找到2个数和为0-a,是不是就和2SUM问题一样了?
其实这题相比2SUM多了几个难点:
1. 数组里允许重复的数
2. 结果要按升序排列
3. 结果中不能出现重复的结果
当然,我们可以通过写很多条判断语句解决这些问题,但是其实稍微想一下,可以发现,只要保证数组一开始就有序就好办很多了。
我们可以选择3个变量,left,mid,right。在循环的时候,永远保证相对顺序就行了。这样在插入结果的时候,就自然是升序的。
我们可以参考2SUM的思路2解决这道题。
首先,我们考虑如何确定第一个数left,这肯定是我们第一层循环。第一个数可不能无限制的随便选,因为我们要保证上面的几个条件都满足,我们要保证它时刻是最小的数,那么我们可以考虑left取到全部非正数就行了。(如果要和为0,至少要有1个非正数)
for (int left = 0; left < nums.length && nums[left] <= 0; left++)
然后就是mid和right的确定了,我们采用思路2的方案,mid和right分别从两端往中央扫描,如果mid+right还比较小,那就需要mid右移,反之right左移
我们可以写出如下的代码:
mid = left+1; right = nums.length-1;
while(mid < right)
{
int tmp = 0-nums[left];
if(nums[mid] + nums[right] == tmp)
addtolist;
else if(nums[mid] + nums[right] < tmp)
mid++;
else
right--;
}
一切看起来特别美好了,可以当你提交的时候,你会发现,还是会报错,因为它虽然能解决问题2,但是不能处理重复结果。举个最简单的例子:
-2 -2 -1 -1 0 1 1 2 2
这个代码会输出数个[-2 0 2] [-1 0 1] ,解决方案也很简单,如果一个left指向的数是之前判断过的,跳过,如果mid和right往中间移动的时候,是刚才的数,也跳过。
mid = left+1; right = nums.length-1;
while(mid < right)
{
int tmp = 0-nums[left];
//跳过left重复匹配
if(left > 0 && nums[left] == nums[left-1])
continue;
if(nums[mid] + nums[right] == tmp)
{
int tmp_mid = nums[mid],tmp_right= nums[right];
list.add(Arrays.asList(nums[left], nums[mid], nums[right]));
//跳过right和mid的重复匹配
while(mid < right && nums[++mid] == tmp_mid);
while(mid < right && nums[--right] == tmp_right);
}
else if(nums[mid] + nums[right] < tmp)
mid++;
else
right--;
}
代码
public class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> list;
list = new ArrayList<List<Integer>>();
int mid,right;
//left只用循环所有的非正数就行了(不是负数是因为还要考虑[0 0 0]的情况所以是非正数)
for (int left = 0; left < nums.length && nums[left] <= 0; left++) {
mid = left+1; right = nums.length-1;
int tmp = 0-nums[left];
//跳过left重复匹配
if(left > 0 && nums[left] == nums[left-1])
continue;
while(mid < right)
{
if(nums[mid] + nums[right] == tmp)
{
int tmp_mid = nums[mid],tmp_right= nums[right];
list.add(Arrays.asList(nums[left], nums[mid], nums[right]));
//跳过right和mid的重复匹配
while(mid < right && nums[++mid] == tmp_mid);
while(mid < right && nums[--right] == tmp_right);
}
else if(nums[mid] + nums[right] < tmp)
mid++;
else
right--;
}
}
return list;
}
}
《LeetBook》leetcode题解(15):3Sum[M]的更多相关文章
- 【LeetCode】15. 3Sum 三数之和
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人公众号:负雪明烛 本文关键词:3sum, 三数之和,题解,leetcode, 力扣,P ...
- LeetCode:15. 3Sum(Medium)
1. 原题链接 https://leetcode.com/problems/3sum/description/ 2. 题目要求 数组S = nums[n]包含n个整数,请问S中是否存在a,b,c三个整 ...
- 《LeetBook》leetcode题解(16):3Sum Closest [M]
我现在在做一个叫<leetbook>的免费开源书项目,力求提供最易懂的中文思路,目前把解题思路都同步更新到gitbook上了,需要的同学可以去看看 书的地址:https://hk029.g ...
- 【一天一道LeetCode】#15 3Sum
一天一道LeetCode系列 (一)题目 Given an array S of n integers, are there elements a, b, c in S such that a + b ...
- LeetCode OJ 15. 3Sum
题目 Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all ...
- Leetcode Array 15 3sum
思考的方向不对,即使用了多于别人几倍的时间,也不一定能够达到终点. 我的错误的想法(可以跳过):在leetcode上面做的第四道题,走路一个很大的弯路,收到之前做过的 Container With ...
- 【LeetCode】15. 3Sum 三个数和为0
题目: Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find al ...
- 【leetcode】15. 3Sum
题目描述: Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find ...
- LeetCode题解 15题 第二篇
之前写过一篇,这是第二篇.上一篇用了多种编程语言来做,这一次是以学算法为主,所以打算都用python来完成. 4. Median of Two Sorted Arrays There are two ...
随机推荐
- ENVI数据格式
选择一个或多个感兴趣的图层: 分类:目视解译.非监督分类 投影 哪里需要七参数,没有必要七参数吧?如果精度要求不高的话
- (KMP 求循环节)The Minimum Length
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=70325#problem/F The Minimum Length Time Limit: ...
- HDU6029 Graph Theory 2017-05-07 19:04 40人阅读 评论(0) 收藏
Graph Theory Time Limit: 2000/1000 M ...
- [php] cookie 跨域共享
<?php // m.hinabian.com class Controller_Cookie extends Hnb_Base_Controller { public function ini ...
- JS的__proto__与prototype
一.prototype和__proto__的概念 prototype是函数的一个属性(每个函数都有一个prototype属性),这个属性是一个指针,指向一个对象.它是显示修改对象的原型的属性. __p ...
- [leetcode] 17. Merge Two Sorted Lists
这个非常简单的题目,题目如下: Merge two sorted linked lists and return it as a new list. The new list should be ma ...
- [LeetCode 题解]:Palindrome Number
前言 [LeetCode 题解]系列传送门: http://www.cnblogs.com/double-win/category/573499.html 1.题目描述 Determine ...
- Alwayson--问题总结二
1. 备份首选项作用 答:备份首选项并不影响实际的备份操作,只是在备份前提供标示当前副本是否是推荐的备份副本.管理员可以忽略备份首选项在任意副本上执行完整备份和日志备份. 2. 在辅助副本和主副本备份 ...
- Install Nginx on CentOS 7
To set up the yum repository for RHEL/CentOS, create the file named /etc/yum.repos.d/nginx.repo with ...
- Elasticsearch、Kibana Windows下环境搭建
Elasticsearch 簡介 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是 ...