【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
相关推荐
琢磨先生David4 天前
Day1:基础入门·两数之和(LeetCode 1)
数据结构·算法·leetcode
超级大福宝4 天前
N皇后问题:经典回溯算法的一些分析
数据结构·c++·算法·leetcode
Charlie_lll4 天前
力扣解题-88. 合并两个有序数组
后端·算法·leetcode
菜鸡儿齐4 天前
leetcode-最小栈
java·算法·leetcode
Frostnova丶4 天前
LeetCode 1356. 根据数字二进制下1的数目排序
数据结构·算法·leetcode
im_AMBER5 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
样例过了就是过了5 天前
LeetCode热题100 环形链表 II
数据结构·算法·leetcode·链表
tyb3333335 天前
leetcode:吃苹果和队列
算法·leetcode·职场和发展
踩坑记录5 天前
leetcode hot100 74. 搜索二维矩阵 二分查找 medium
leetcode
TracyCoder1235 天前
LeetCode Hot100(60/100)——55. 跳跃游戏
算法·leetcode