15. 三数之和

image

15. 三数之和

思路

要找出所有和为0且不重复的三元组,可以使用排序+双指针的策略:

  1. 排序数组:预处理数组,便于跳过重复元素和使用双指针

  2. 固定一个元素:遍历数组,固定当前元素 nums[i]

  3. 双指针寻找匹配元素

    • 左指针 left = i + 1
    • 右指针 right = nums.length - 1
    • 计算 nums[i] + nums[left] + nums[right] 的和
  4. 根据和调整指针

    • 和=0:找到有效三元组,记录结果并跳过重复元素
    • 和<0:左指针右移(增加总和)
    • 和>0:右指针左移(减小总和)
  5. 跳过重复元素:在每一步跳过重复值,避免重复三元组

复杂度分析

  • 时间复杂度:O(n²)
    排序 O(n log n) + 双指针扫描 O(n²) → 总体 O(n²)
  • 空间复杂度:O(1)
    除结果集外,仅使用常数额外空间(排序占用 O(log n) 栈空间)

代码

import java.util.*;

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums); // 排序数组
        
        for (int i = 0; i < nums.length - 2; i++) {
            // 跳过重复的固定元素
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            
            // 提前终止:最小元素已大于0
            if (nums[i] > 0) break;
            
            int left = i + 1, right = nums.length - 1;
            while (left < right) {
                int sum = nums[i] + nums[left] + nums[right];
                
                if (sum == 0) {
                    result.add(Arrays.asList(nums[i], nums[left], nums[right]));
                    // 跳过左侧重复元素
                    while (left < right && nums[left] == nums[left + 1]) left++;
                    // 跳过右侧重复元素
                    while (left < right && nums[right] == nums[right - 1]) right--;
                    // 移动到下一组不同元素
                    left++;
                    right--;
                } else if (sum < 0) {
                    left++; // 需要更大的数
                } else {
                    right--; // 需要更小的数
                }
            }
        }
        return result;
    }
}

posted @ 2025-07-30 01:24  quanht  阅读(8)  评论(0)    收藏  举报