015三数之和

写在前面,参考力扣官网的画解算法。。真的太清晰明了了

一、java代码

/*
 * @lc app=leetcode.cn id=15 lang=java
 *
 * [15] 三数之和
 */

// @lc code=start
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        //ans接收答案
        List<List<Integer>> ans=new ArrayList();
        //给定nums数组长度
        int len=nums.length;
        //当给定数组为空或者长度小于3则直接返回ans
        if(nums==null||len<3) return ans;
        //首先对数组进行排序
        Arrays.sort(nums);//排序
        //固定i
        for(int i=0;i<len;i++){
            //后面的也会大于0 ,所以在此处终结
            if(nums[i]>0) break;//如果当前数字大于0,则三数之和必定大于0,结束循环

            //返回for循环,i++
            if(i>0&&nums[i]==nums[i-1]) continue;//去重
            //使用左右指针指向nums[i]后面的两端
            int L=i+1;
            int R=len-1;
            //当L<R时才能继续下面的判断,否则i++
            while(L<R){
                //核心公式
                int sum=nums[i]+nums[L]+nums[R];
                //当sum==0是,左加右减收缩
                if(sum==0){
                    //将当前结果存到ans中
                    ans.add(Arrays.asList(nums[i],nums[L],nums[R]));
                    //当`sum==0`时,`nums[L]==nums[L+1]`,则会导致结果重复,应该跳过,`L++`
                    while(L<R && nums[L]==nums[L+1]) L++;//去重
                    //当`sum==0`时,`nums[R]==nums[R-1]`,则会导致结果重复,应该跳过,`R--`
                    while(L<R && nums[R]==nums[R-1]) R--;//去重
                    //左加右减
                    L++;
                    R--;
                }
                else if(sum<0) L++;
                else if(sum>0) R--;
            }
        }
        return ans;

    }
}
// @lc code=end

二、解题思路

  1、首先对数组进行排序,排序后固定一个数nums[i]
  2、再使用左右指针,指向nums[i]后面部分的两端,数字分别为nums[L]nums[R]
  3、计算三个数的和sum,判断是否满足为0,满足则添加进结果集ans

  (1)如果nums[i]大于0,则三数之后必然无法大于0,结束循环

  (2)如果nums[i]==nums[i-1],则说明该数字重复,会导致结果重复,所以跳过

  (3)当sum==0时,nums[L]==nums[L+1],则会导致结果重复,应该跳过,L++

  (4)当sum==0时,nums[R]==nums[R-1],则会导致结果重复,应该跳过,R--

三、图解

(1/12)

(2/12)

(3/12)

(4/12)

(5/12)

(6/12)

(7/12)

(8/12)

(9/12)

(10/12)

(11/12)

(12/12)

四、动图演示

原文地址:https://www.cnblogs.com/lxr-xiaorong/p/13597382.html