Day10 三數(shù)之和

給你一個(gè)包含 n 個(gè)整數(shù)的數(shù)組 nums,判斷 nums 中是否存在三個(gè)元素 a,b,c ,使得 a + b + c = 0,請(qǐng)你找出所有和為 0 且不重復(fù)的三元組

https://leetcode-cn.com/problems/3sum/

示例1:

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

示例2:

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

示例3:

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

提示:

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

Java解法

思路:

  • 熟悉的遍歷算法,條件不一致,取出第一個(gè)數(shù),遍歷剩下的數(shù)中滿足b+c=-a
  • 沒那么簡(jiǎn)單,自己坑了自己,去重是不能去的,應(yīng)該要先排序的
  • 先排序(熟悉了下快排),然后依次遍歷數(shù)據(jù),注意若數(shù)據(jù)與前一位相同則需要跳過(guò)(排過(guò)序所以不用擔(dān)心需要往前找),中間要記得優(yōu)化,數(shù)據(jù)越來(lái)越大的,所以相加為0的數(shù)據(jù)必定是兩端往內(nèi)部收斂
  • 存入數(shù)據(jù)忘記判斷條件,導(dǎo)致超時(shí)驗(yàn)證,自行運(yùn)行花了5秒,還是錯(cuò)的,要注意
package sj.shimmer.algorithm;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by SJ on 2021/2/3.
 */

class D10 {
    public static void main(String[] args) {
        System.out.println(threeSum(new int[]{-1, 0, 1, 2, -1, -4}));
        System.out.println(threeSum(new int[]{0}));
        System.out.println(threeSum(new int[]{0,0,0}));
    }

    public static List<List<Integer>> threeSum(int[] nums) {
        ArrayList<List<Integer>> results = new ArrayList<>();
        if (nums == null || nums.length < 3) {
            return results;
        }
        quickSort(nums, 0, nums.length - 1);
        Utils.logTime();

        for (int i = 0; i < nums.length; i++) {
            if (nums[i] > 0) {
                break;
            }
            if (i > 0 && nums[i] == nums[i-1]) {
                continue;
            }
            int k = nums.length-1;
            for (int j = i + 1; j < nums.length; j++) {
                if (j > i + 1 && nums[j] == nums[j-1]) {
                    continue;
                }
                //定了唯一的 i,j  就只有唯一的k
                while (j<k&&nums[i] +nums[j] +nums[k]>0){
                    k--;
                }
                if (j==k) {
                    //這一輪再也查不到了
                    break;
                }
                if (nums[i] +nums[j] +nums[k]==0) {
                    List<Integer> integers = new ArrayList<>();
                    integers.add(nums[i]);
                    integers.add(nums[j]);
                    integers.add(nums[k]);
                    results.add(integers);
                }
            }
        }

        return results;
    }


    private static int[] quickSort(int[] arr, int left, int right) {
        if (left < right) {
            //找到基準(zhǔn)交換后的位置、作為下次分割邊界
            int spiltIndex = findPonitIndex(arr, left, right);
            quickSort(arr, left, spiltIndex - 1);
            quickSort(arr, spiltIndex + 1, right);
        }
        return arr;
    }

    private static int findPonitIndex(int[] arr, int left, int right) {
        int point = arr[left];//以左邊界為比較基準(zhǔn)值
        while (left < right) {
            //以左為基準(zhǔn),先從右側(cè)遍歷,小于基準(zhǔn)交互
            while (point <= arr[right] && left < right) {
                right--;
            }
            if (left < right) {
                //未相遇, 第一個(gè)左側(cè)值是基準(zhǔn),已被記錄
                arr[left] = arr[right];
            }
            //左側(cè)遍歷,大于基準(zhǔn)跳出
            while (point > arr[left] && left < right) {
                left++;
            }
            if (left < right) {
                //未相遇, 第一個(gè)右側(cè)值移至原基準(zhǔn)位置,已被記錄
                arr[right] = arr[left];
            }
        }
        arr[left] = point;
        return left;
    }
}
image

官方解

  1. 排序 + 雙指針

    我參考的就是這種寫法,但他們排序用的直接是Arrays.sort(nums);

    官方解優(yōu)化了三重循環(huán)的第二次與第三次,因?yàn)橛行?,且結(jié)果固定,所以用雙指針優(yōu)化了該嵌套

    • 時(shí)間復(fù)雜度: O(N2),其中 N 是數(shù)組 nums 的長(zhǎng)度
    • 空間復(fù)雜度:O(logN)。忽略存儲(chǔ)答案的空間,額外的排序的空間復(fù)雜度為O(logN)。然而我們修改了輸入的數(shù)組 nums,在實(shí)際情況下不一定允許,因此也可以看成使用了一個(gè)額外的數(shù)組存儲(chǔ)了 nums 的副本并進(jìn)行排序,空間復(fù)雜度為 O(N)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容