【Golang】LeetCode 15. 三数之和

15. 三数之和

题目描述

思路

今天我们来回顾经典的三数之和问题。

解决这个问题的思路实际上就是对排序过的数组使用双指针。首先我们需要对数组进行排序;针对排序过后的数组,我们使用x表示当前我们正在遍历的数组下标i对应的值,设置两个指针jkj的初始值是i + 1k的初始值是n - 1(此处的n是数组长度)。我们开始向中间移动这两个指针,如果满足:x + nums[j] + nums[k] > 0,则应该将k向左移动,因为我们应该削减数值最大的那个数才能够让三数之和有可能等于零;反之如果x + nums[j] + nums[k] < 0,那么我们应该将j向右移动,原因是只有将较小的数调大才有机会找到三数之和为零的情况。如果这个和为零,则代表我们找到了一个三数之和。

由于题目中明确要求不能有重复,所以我们找到一个答案之后需要进行一次去重,方法也很简单,那就是向中间移动jk,如果nums[j] == nums[j - 1]则向右移动j,如果nums[k] == nums[k + 1]则向左移动k

这道题目在对当前数组的下标i进行遍历的时候有三个缩减遍历空间的小技巧:

  1. 如果i != 0nums[i] == nums[i - 1],则直接向右移动i,因为题目要求不能出现重复的答案;
  2. 如果nums[i] + nums[i + 1] + nums[i + 2] > 0,那么我们就可以停止遍历了,因为数组已经经过了排序,后面的数值不会再出现三数之和为零的情况了;
  3. 如果nums[i] + nums[n - 1] + nums[n - 2] < 0,则代表当前遍历的数值加上数组当中最大的两个数之和,其值仍然小于零,对当前这个数进行双指针寻找三数之和为零的情况一定是找不到的,此时我们应该继续向右移动i

基于以上思路,我们写代码来解决问题。

Golang 题解

go 复制代码
func threeSum(nums []int) [][]int {
    sort.Slice(nums, func(i, j int) bool {
        return nums[i] < nums[j]
    })

    ans := [][]int{}
    n := len(nums)
    for i := 0; i < n - 2; i ++ {
        x := nums[i]
        if i > 0 && x == nums[i - 1] {
            continue
        }
        if x + nums[n - 1] + nums[n - 2] < 0 {
            continue
        }
        if x + nums[i + 1] + nums[i + 2] > 0 {
            break
        }
        j, k := i + 1, n - 1
        for j < k {
            sum := x + nums[j] + nums[k]
            if sum > 0 {
                k --
            } else if sum < 0 {
                j ++
            } else {
                ans = append(ans, []int{x, nums[j], nums[k]})
                j, k = j + 1, k - 1
                for j < k && nums[j] == nums[j - 1] {
                    j ++
                }
                for j < k && nums[k] == nums[k + 1] {
                    k --
                }
            }
        }
    }

    return ans
}

Python 题解

python 复制代码
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        ans, n = [], len(nums)

        i = 0
        while i < n - 2:
            x = nums[i]
            if i > 0 and x == nums[i - 1]:
                i += 1
                continue
            if x + nums[i + 1] + nums[i + 2] > 0:
                break
            if x + nums[n - 1] + nums[n - 2] < 0:
                i += 1
                continue

            j, k = i + 1, n - 1
            while j < k:
                sum = x + nums[j] + nums[k]
                if sum > 0:
                    k -= 1
                elif sum < 0:
                    j += 1
                else:
                    ans.append([x, nums[j], nums[k]])
                    j, k = j + 1, k - 1
                    while j < k and nums[j] == nums[j - 1]:
                        j += 1
                    while j < k and nums[k] == nums[k + 1]:
                        k -= 1

            i += 1

        return ans
相关推荐
普贤莲花1 小时前
【2026年第18周---写于20260501】---舍得
程序人生·算法·leetcode
m0_629494731 小时前
LeetCode 热题 100-----16.除了自身以外数组的乘积
数据结构·算法·leetcode
We་ct2 小时前
LeetCode 97. 交错字符串:动态规划详解
前端·算法·leetcode·typescript·动态规划
无敌昊哥战神2 小时前
【LeetCode 37】解数独 (Sudoku Solver) —— 回溯法详解 (Python/C/C++)
c语言·c++·python·算法·leetcode
风筝在晴天搁浅2 小时前
LeetCode 162.寻找峰值
算法·leetcode
罗超驿3 小时前
双指针算法经典案例:LeetCode 283. 移动零(Java详解)
java·算法·leetcode
人道领域3 小时前
【数据结构与算法分析】二叉树面试通关手册:遍历图解 · 分类对比 · 代码模板
数据结构·算法·leetcode·深度优先
水蓝烟雨3 小时前
2901. 最长相邻不相等子序列 II
算法·leetcode
承渊政道3 小时前
【动态规划算法】(回文串问题解题框架与经典案例)
数据结构·c++·学习·算法·leetcode·动态规划·哈希算法
We་ct8 小时前
LeetCode 5. 最长回文子串:DP + 中心扩展
前端·javascript·算法·leetcode·typescript