【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
相关推荐
医用门2 小时前
医院用门一线品牌
leetcode
he___H4 小时前
leetcode100-普通数组
java·数据结构·算法·leetcode
菜菜的顾清寒7 小时前
力扣HOT100(30)两两交换链表中的节点
算法·leetcode·链表
csdn_aspnet9 小时前
C++ 算法 LeetCode 编号 70 - 爬楼梯
开发语言·c++·算法·leetcode
圣保罗的大教堂9 小时前
leetcode 2770. 达到末尾下标所需的最大跳跃次数 中等
leetcode
姚不倒10 小时前
从「LeetCode LRU 缓存」到「生产级 Go Web 服务」:我如何迈出工程化第一步
leetcode·缓存·云原生·golang
sheeta199810 小时前
LeetCode 每日一题笔记 日期:2026.05.25 题目:1871. 跳跃游戏 VII
笔记·leetcode·游戏
XWalnut10 小时前
LeetCode刷题 day20
java·算法·leetcode
csdn_aspnet11 小时前
C# 算法 LeetCode 编号 70 - 爬楼梯
算法·leetcode·c#
过期动态11 小时前
【LeetCode 热题 100】最长连续序列
java·数据结构·spring boot·算法·leetcode·职场和发展