天天看點

利用「排序」&「雙指針」解決三數之和問題|Java

題目描述

這是 LeetCode 上的 ​​15. 三數之和​​ ,難度為 中等。

Tag : 「雙指針」、「排序」、「n 數之和」

給你一個包含 n 個整數的數組 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?

請你找出所有和為 0 且不重複的三元組。

注意:答案中不可以包含重複的三元組。

示例 1:

輸入:nums = [-1,0,1,2,-1,-4]
輸出:[[-1,-1,2],[-1,0,1]]      

示例 2:

輸入:nums = []
輸出:[]      

示例 3:

輸入:nums = [0]
輸出:[]      

提示:

  • 0 <= nums.length <= 3000
  • -<= nums[i] <=

排序 + 雙指針

對數組進行排序,使用三個指針 ​

​i​

​​、​

​j​

​​ 和 ​

​k​

​ 分别代表要找的三個數。

  1. 通過枚舉 ​

    ​i​

    ​ 确定第一個數,另外兩個指針 ​

    ​j​

    ​,​

    ​k​

    ​ 分别從左邊 ​

    ​i + 1​

    ​ 和右邊 ​

    ​n - 1​

    ​ 往中間移動,找到滿足 ​

    ​nums[i] + nums[j] + nums[k] == 0​

    ​ 的所有組合。
  2. ​j​

    ​ 和 ​

    ​k​

    ​ 指針的移動邏輯,分情況讨論 ​

    ​sum = nums[i] + nums[j] + nums[k]​

    ​ :
  • ​sum​

    ​​ > 0:​

    ​k​

    ​​ 左移,使​

    ​sum​

    ​ 變小
  • ​sum​

    ​​ < 0:​

    ​j​

    ​​ 右移,使​

    ​sum​

    ​ 變大
  • ​sum​

    ​ = 0:找到符合要求的答案,存起來

由于題目要求答案不能包含重複的三元組,是以在确定第一個數和第二個數的時候,要跳過數值一樣的下标(在三數之和确定的情況下,確定第一個數和第二個數不會重複,即可保證三元組不重複)。

代碼:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        int n = nums.length;
        List<List<Integer>> ans = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            int j = i + 1, k = n - 1;
            while (j < k) {
                while (j > i + 1 && j < n && nums[j] == nums[j - 1]) j++;
                if (j >= k) break;
                int sum = nums[i] + nums[j] + nums[k];
                if (sum == 0) {
                    ans.add(Arrays.asList(nums[i], nums[j], nums[k]));
                    j++;
                } else if (sum > 0) {
                    k--;
                } else if (sum < 0) {
                    j++;
                }
            }
        }
        return ans;
    }
}      
  • 時間複雜度:排序的複雜度為,對于每個​​

    ​i​

    ​​ 而言,最壞的情況​

    ​j​

    ​​ 和​

    ​k​

    ​​ 都要掃描一遍數組的剩餘部分,複雜度為。整體複雜度為
  • 空間複雜度:

最後

這是我們「刷穿 LeetCode」系列文章的第 ​

​No.15​

​ 篇,系列開始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道題目,部分是有鎖題,我們将先将所有不帶鎖的題目刷完。

繼續閱讀