1. 程式人生 > 實用技巧 >015三數之和

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)

四、動圖演示