思考的方向不对,即使用了多于别人几倍的时间,也不一定能够达到终点。

我的错误的想法(可以跳过):在leetcode上面做的第四道题,走路一个很大的弯路,收到之前做过的 Container With Most Water 的思路的影响,自己也想到了可以使用两个指针从左右遍历数组, 然而自己在这里走偏了,上来的第一个想法就是可以将整个解集合分为四种情况:全零,一正一负一零,两正一负,两负一正。这样整个程序就大致分为了四块,出现这种想法是由于我在第一层循环上面使用了两个指针向中间遍历,为内循环里面选择了一个指针分别根据四种情况来决定从哪边开始遍历。这时每种情况都需要控制相似的条件,而且需要控制的条件也比较多,这里就不在赘述了,将自己的代码贴一下,警醒一下自己。。(过了126组数据)

public class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> LL = new ArrayList<List<Integer>>();
List<Integer> L = new ArrayList<Integer>();
if(nums.length<3)
return LL;
//先对数组进行排序
Arrays.sort(nums);
//寻找数组中可能存在的零
int index0 = 0;
boolean bIndex = false;
while(index0<nums.length){
if(nums[index0] == 0){
bIndex = true;
break;
}
index0++;
}
//首位为0
if(bIndex){
int c = 0;
int t0 = index0;
while(t0<nums.length){
if(nums[t0++] == 0)
c++;
else
break;
}
if(c>=3){
L.add(0);
L.add(0);
L.add(0);
LL.add(L);
L = new ArrayList<Integer>();
}
}
int i=0,j=nums.length-1;
//一正一负一零
if(bIndex){
while(i<index0 && j>index0){
if(Math.abs(nums[i]) == Math.abs(nums[j])){
L.add(nums[i]);
L.add(0);
L.add(nums[j]);
LL.add(L);
L = new ArrayList<Integer>();
while(nums[i] == nums[i+1]){
i++;
}
while(nums[j] == nums[j-1]){
j--;
}
i++;j--;
}
else if(Math.abs(nums[i])>Math.abs(nums[j])){
i++;
}
else{
j--;
}
}
}
//两负一正
i=0;j=nums.length-1;
while(i<j && nums[i]*nums[j]<0){
if(Math.abs(nums[i])>=Math.abs(nums[j])){ // 负数的绝对值大于正数的 不可能有两负一
i++;
continue;
}
//
int k=i+1;
for(;nums[k]<0;k++){ //这里还可以优化```
if(-(nums[i]+nums[k]) < nums[j]){
j--;
break;
}
if(nums[i]+nums[k] == -nums[j]){
L.add(nums[i]);
L.add(nums[k]);
L.add(nums[j]);
LL.add(L);
L = new ArrayList<Integer>();
//去除重复
while(nums[i+1] == nums[i]){
i++;
}
if(nums[i] != nums[k]) // -4 -4 8 -4 -1 5
i++;
break;
}
}
if(nums[k]>=0){ //去除重复
while(nums[j-1] == nums[j]){
j--;
}
j--;
}
}
//两正一负
i=0;j=nums.length-1;
while(i<j && nums[i]*nums[j]<0){
if(Math.abs(nums[i])<=Math.abs(nums[j])){ // 负数的绝对值大于正数的 不可能有两负一
j--;
continue;
}
int k = j-1;
for(;nums[k]>0;k--){
if(nums[k]+nums[j] < -nums[i]){
i++;
break;
}
if(nums[k]+nums[j] == -nums[i]){
L.add(nums[i]);
L.add(nums[k]);
L.add(nums[j]);
LL.add(L);
L = new ArrayList<Integer>(); while(nums[j] == nums[j-1])
j--;
if(nums[j] != nums[k])
j--;
break;
}
}
if(nums[k]<=0){
while(nums[i] == nums[i+1]){
i++;
}
i++;
}
}
return LL;
}
}

在看了别人的代码之后自己感觉恍然大悟,只要在外层循环从左到右遍历一遍(跳过重复的数据),然后内层循环按照 two sum的做法,将外循环遍历得到的值的相反数作为内循环的target就可以了,然后left,right分别遍历,所得到的值大于target就right--,否则left++ ,在++,--的过程中需要跳过重复值。代码如下:

public class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> LL = new ArrayList<List<Integer>>();
int len = nums.length;
if(len<3)
return LL;
Arrays.sort(nums);
for(int i=0;i<len;i++){
if(nums[i]>0)
break;
if(i>0&&nums[i] == nums[i-1])
continue;
int begin = i+1,end = len-1;
while(begin<end){
int sum = nums[i]+nums[begin]+nums[end];
if(sum == 0){
List<Integer> L = new ArrayList<Integer>();
L.add(nums[i]);
L.add(nums[begin]);
L.add(nums[end]);
LL.add(L);
begin++;end--;
while(begin<end && nums[begin]==nums[begin-1])begin++;
while(begin<end && nums[end]==nums[end+1])end--;
}
else if(sum>0)
end--;
else
begin++;
}
}
return LL;
}
}

下面的这种方法可以更好的理解:第一层循环作为target:

    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--;
}
}
}
}

注意,对于 num[i],寻找另外两个数时,只要从 i+1 开始找就可以了。

这种写法,可以避免结果集中有重复,因为数组时排好序的,所以当一个数被放到结果集中的时候,其后面和它相等的直接被跳过。

 

Leetcode Array 15 3sum的更多相关文章

  1. 【LeetCode】15. 3Sum 三数之和

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人公众号:负雪明烛 本文关键词:3sum, 三数之和,题解,leetcode, 力扣,P ...

  2. LeetCode:15. 3Sum(Medium)

    1. 原题链接 https://leetcode.com/problems/3sum/description/ 2. 题目要求 数组S = nums[n]包含n个整数,请问S中是否存在a,b,c三个整 ...

  3. 【一天一道LeetCode】#15 3Sum

    一天一道LeetCode系列 (一)题目 Given an array S of n integers, are there elements a, b, c in S such that a + b ...

  4. 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 ...

  5. 《LeetBook》leetcode题解(15):3Sum[M]

    我现在在做一个叫<leetbook>的免费开源书项目,力求提供最易懂的中文思路,目前把解题思路都同步更新到gitbook上了,需要的同学可以去看看 书的地址:https://hk029.g ...

  6. Leetcode Array 16 3Sum Closest

    Given an array S of n integers, find three integers in S such that the sum is closest to a given num ...

  7. 【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 ...

  8. 【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 ...

  9. [LeetCode]题15:3Sum

    第一次解: res = [] nums.sort() if len(nums)<3:return [] for i in range(len(nums)-2): left = i+1 right ...

随机推荐

  1. 编程风格——UNIX 高手的 10 个习惯

    引言 当您经常使用某个系统时,往往会陷入某种固定的使用模式.有时,您没有养成以尽可能最好的方式做事的习惯.有时,您的不良习惯甚至会导致出现混乱.纠正此类缺点的最佳方法之一,就是有意识地采用抵制这些坏习 ...

  2. HDU 5696 RMQ+滑窗

    区间的价值 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Subm ...

  3. tomcat镜像构建

    1.目录结构与配置文件如下 [root@centos05 java]# tree . ├── apache-tomcat-.tar.gz ├── Dockerfile ├── jdk-8u45-lin ...

  4. BZOJ 1658 Water Slides 滑水

    Water Slides 滑水 [问题描述] It's a hot summer day, and Farmer John is letting Betsy go to the water park ...

  5. eclipse在linux下无故闪退解决

    A fatal error has been detected by the Java Runtime Environment: SIGSEGV (0xb) at pc=0x00007f25d0b92 ...

  6. 将一个二叉树左右翻转(Java 版)

    public class Solution { public TreeNode invertTree(TreeNode root) { if (root == null) { return null; ...

  7. linux下kodi没有声音的解决

    前几天,心血来潮,就安装了manjaro的pre3版本,由于是mini kde版本的,就随手安装了kodi,可以用来看视频,听音乐和看图片. 结果在所有插件都折腾好了之后发现,在屏幕的右上角有一个喇叭 ...

  8. 2018年东北农业大学春季校赛 I wyh的物品【01分数规划/二分】

    链接:https://www.nowcoder.com/acm/contest/93/I来源:牛客网 题目描述 wyh学长现在手里有n个物品,这n个物品的重量和价值都告诉你,然后现在让你从中选取k个, ...

  9. Codeforces 632F Magic Matrix(bitset)

    题目链接  Magic Matrix 考虑第三个条件,如果不符合的话说明$a[i][k] < a[i][j]$ 或 $a[j][k] < a[i][j]$ 于是我们把所有的$(a[i][j ...

  10. gtest 自动化测试 部署

    1.部署 a)编译框架 1.1下载gtest库1.6.0 并解压到文件夹 "/user/{user}/gtest.1.6.0" 下载地址:https://code.google.c ...