【LeetCode】15. 三数之和

leetcode

 

问题分析

题目要求找出数组中所有满足条件的三元组 [nums[i], nums[j], nums[k]],使得三数之和为 0,且结果不重复。核心难点在于 ​高效去重 和 ​优化时间复杂度。以下是基于搜索结果的 Golang 实现方案:


实现思路

1. ​排序与双指针法

  • 排序:对数组排序后,便于跳过重复元素和调整指针方向。
  • 双指针策略
    1. 固定第一个数 nums[i],然后用左右指针 left 和 right 在剩余区间搜索两数之和为 -nums[i] 的组合。
    2. 若三数之和 >0,则右指针左移;若 <0,则左指针右移;若 =0,记录结果并去重。
  • 时间复杂度O(n^2),优于暴力三重循环的 O(n^3)

2. ​去重逻辑

  • 外层循环去重:当 nums[i] == nums[i-1] 时跳过,避免重复固定相同的第一个数。
  • 内层双指针去重:找到有效三元组后,跳过所有与 nums[left] 和 nums[right] 相同的相邻元素。

3. ​剪枝优化

  • 提前终止:若 nums[i] > 0,由于数组已排序,后续无法找到三数和为 0 的组合,直接终止循环。

Golang 实现代码

import "sort"

func threeSum(nums []int) [][]int {
    sort.Ints(nums)  // 先排序
    result := [][]int{}
    n := len(nums)

    for i := 0; i < n-2; i++ {
        // 跳过重复的第一个数
        if i > 0 && nums[i] == nums[i-1] {
            continue
        }
        // 剪枝:若第一个数已大于0,后续无解
        if nums[i] > 0 {
            break
        }

        left, right := i+1, n-1
        target := -nums[i]

        for left < right {
            sum := nums[left] + nums[right]
            if sum == target {
                result = append(result, []int{nums[i], nums[left], nums[right]})
                // 跳过重复的左右指针元素
                for left < right && nums[left] == nums[left+1] {
                    left++
                }
                for left < right && nums[right] == nums[right-1] {
                    right--
                }
                left++
                right--
            } else if sum < target {
                left++
            } else {
                right--
            }
        }
    }
    return result
}

 


关键点说明

  1. 排序的作用

    • 确保相同值的元素相邻,便于去重。
    • 双指针的移动方向可预测,便于调整搜索范围。
  2. 去重逻辑的细节

    • 外层循环去重条件为 i > 0 && nums[i] == nums[i-1],而非 i < n-2 && nums[i] == nums[i+1],避免遗漏有效组合。
    • 内层循环去重需在记录结果后立即处理,防止重复添加相同三元组。
  3. 性能优化

    • 排序后提前终止循环(nums[i] > 0)减少无效计算。
    • 双指针法将时间复杂度优化至 O(n^2)。

测试示例验证

  • 示例1:输入 [-1,0,1,2,-1,-4],输出 [[-1,-1,2],[-1,0,1]]
  • 示例2:输入 [0,1,1],输出 []
  • 示例3:输入 [0,0,0],输出 [[0,0,0]]

复杂度分析

维度说明
时间复杂度 O(n^2)(排序 O(nlogn) + 双指针 O(n^2)
空间复杂度 O(1)(忽略排序的栈空间)

扩展与优化

  • 四数之和:可参考双指针法的扩展,固定前两个数,再用双指针搜索后两数。
  • 哈希表法:虽可实现但需额外空间存储中间结果,且去重逻辑复杂,推荐优先使用双指针。

如需进一步优化内存,可预分配 result 切片容量。

 

posted @ 2025-03-19 17:28  云隙之间  阅读(57)  评论(0)    收藏  举报