【LeetCode-中等】15. 三数之和(图文详解)

发布于:2022-10-14 ⋅ 阅读:(487) ⋅ 点赞:(0)

题目

题目地址:https://leetcode.cn/problems/3sum/

示例

方法1:排序+双指针

思路参考了作者:Krahets

https://leetcode.cn/problems/3sum/solution/3sumpai-xu-shuang-zhi-zhen-yi-dong-by-jyd/

我的思路:

先排序数组

定义三个指针:最左(leftMost)、左(left)、右(right)

最左指针放在数组的最左边,左、右指针放在 最左指针的右边 的左右两段。

如果nums[leftMost]>0,那别找了,没戏了,最左都>0,后面的肯定也>0,不能能三指针相加=0。直接返回结果。

左、右指针一个一个的往中间走:

        当三者相加<0时,left++,并跳过重复的元素

        当三者相加=0时,记录下结果,lefrt和right同时移动:left++ ;right--;并跳过重复的元素

        当三者相加>0时,right--,并跳过重复的元素

当left 不小于 right 时,说明这一轮都找完了,开始将leftMost向右移动,并跳过重复元素,注意,leftMost指的数据一定要<0

举例说明

 

 

 

 

当left 不小于 right ,说明leftMost在当前的情况全部找完了,开始将leftMost右移动,进行新一轮的寻找

 

 

 

这一轮也结束了,leftMost++,并跳过重复

 

 


我写的代码虽然丑,但它宝贵在它是我亲手写的。即使有了思路,代码也不是一下子就能写出来,例如很多的边界条件设置、防止数组越界之类的问题,所以建议照着思路先自己写出一个通过的代码,再去参考别人的代码。

我的代码:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();

        //先排序
        Arrays.sort(nums);

        int leftMost = 0;
        while(leftMost<nums.length-2 && nums[leftMost]<=0){
            int left = leftMost+1;
            int right = nums.length-1;

            while (left<right && left<nums.length-1 &&  right>0){
                int sum = nums[leftMost]+nums[left]+nums[right];
                if (sum == 0){
                    //将正确结果添加上
                    List<Integer> arr = new ArrayList<Integer>();
                    arr.add(nums[leftMost]);
                    arr.add(nums[left]);
                    arr.add(nums[right]);
                    result.add(arr);
                    //left右移 去重
                    if (left<=nums.length-2){
                        while ( left<=nums.length-2 && nums[left] == nums[left+1]){
                            left++;
                        }
                        left++;
                    }else break;;
                    //right左移 去重
                    if (right>=2){
                        while ( right>=2 && nums[right] == nums[right-1]){
                            right--;
                        }
                        right--;
                    }else break;
                }else if (sum < 0){
                    //left右移 去重
                    if (left<=nums.length-2){
                        while ( left<=nums.length-2 && nums[left] == nums[left+1]){
                            left++;
                        }
                        left++;
                    }else break;;
                }else {
                    //right左移 去重
                    if (right>=2){
                        while ( right>=2 && nums[right] == nums[right-1]){
                            right--;
                        }
                        right--;
                    }else break;

                }
            }
            //leftMost右移 去重
            if (leftMost<nums.length-3){
                while (leftMost<nums.length-3 &&  nums[leftMost] == nums[leftMost+1]){
                    leftMost++;
                }
                leftMost++;


            }else break;



        }
        return result;
    }
}

效果

思路有了,写代码也是花费了很多时间,还是得多练 

 别人(Krahets)优秀的代码

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> res = new ArrayList<>();
        for(int k = 0; k < nums.length - 2; k++){
            if(nums[k] > 0) break;
            if(k > 0 && nums[k] == nums[k - 1]) continue;
            int i = k + 1, j = nums.length - 1;
            while(i < j){
                int sum = nums[k] + nums[i] + nums[j];
                if(sum < 0){
                    while(i < j && nums[i] == nums[++i]);
                } else if (sum > 0) {
                    while(i < j && nums[j] == nums[--j]);
                } else {
                    res.add(new ArrayList<Integer>(Arrays.asList(nums[k], nums[i], nums[j])));
                    while(i < j && nums[i] == nums[++i]);
                    while(i < j && nums[j] == nums[--j]);
                }
            }
        }
        return res;
    }
}

效果

我的代码和他的代码思路一样,执行用时也就差不多 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到