首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

3Sum 算法優化:從 O(n³) 暴力到 O(n²) 哈希索引,附去重邏輯與邊界處理

     編輯:Java 綜合教學

題目描述

給定整數數組 nums,找出所有不重複的三元組 [a, b, c],滿足 a + b + c = 0,且 a ≤ b ≤ c。輸出三元組列表,順序不限。

演進路線

第一層:暴力三重循環 O(n³)

for (i=0; i

❌ 超時,大量重複計算。

第二層:排序 + 雙指針 O(n²) —— 經典最優解

  1. 數組排序 Arrays.sort(nums),保證 a ≤ b ≤ c 自然滿足 i < j < k。
  2. 固定第一個數 nums[i],在 i+1 ... n-1 區間雙指針 L,R 尋找 nums[L]+nums[R] = -nums[i]。
  3. 去重關鍵:i>0 && nums[i]==nums[i-1] continue;找到解後 while(L 同理 R--。
public List> threeSum(int[] nums) {
    Arrays.sort(nums);
    List> res = new ArrayList<>();
    for (int i = 0; i < nums.length - 2; i++) {
        if (i > 0 && nums[i] == nums[i-1]) continue; // 跳過重複首元素
        if (nums[i] > 0) break; // 排序後首元素>0,後續全>0,不可能和為0
        int target = -nums[i];
        int L = i + 1, R = nums.length - 1;
        while (L < R) {
            int sum = nums[L] + nums[R];
            if (sum == target) {
                res.add(Arrays.asList(nums[i], nums[L], nums[R]));
                while (L < R && nums[L] == nums[L+1]) L++;
                while (L < R && nums[R] == nums[R-1]) R--;
                L++; R--;
            } else if (sum < target) L++;
            else R--;
        }
    }
    return res;
}

✅ 時間 O(n²),空間 O(1)(不計輸出),代碼簡潔,業界標準解法。

第三層:哈希索引優化查找(本文原始思路)

構建 HashMap> 記錄每個值的所有下標(已排序)。固定 i,j 計算 need = -(nums[i]+nums[j]),查 Map 中是否存在 need 且下標 > j。去重用 Set 記錄 "a#b"。雖同為 O(n²),但常數因子大、代碼複雜,**不推薦生產使用**,僅作為思維拓展。

關鍵優化點總結

優化點作用
排序天然滿足 a≤b≤c,支持雙指針、去重、提前剪枝
首元素 > 0 剪枝後續全正數,直接 break
首元素去重i>0 && nums[i]==nums[i-1] 跳過
雙指針移動單調性保證不遺漏、不重複
找到解後雙指針去重跳過相同值,避免重複三元組

擴展變體

  • 3Sum Closest:找和最接近 target 的三元組,雙指針更新最小差值。
  • 4Sum:固定兩層循環 + 雙指針,O(n³)。
  • 3Sum Smaller:計數和小於 target 的三元組數,雙指針 count += R-L。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved