LeetCode第十五题:三数之和【15/1000 python】

简介: LeetCode第十五题:三数之和【15/1000 python】

👤作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。

会一些的技术:数据分析、算法、SQL、大数据相关、python

欢迎加入社区作者专栏每日更新:

LeetCode解锁1000题: 打怪升级之旅

image.png

备注说明:方便大家阅读,统一使用python,带必要注释,公众号 数据分析螺丝钉 一起打怪升级

在算法和数据结构的学习中,"三数之和"问题是一个非常经典的问题,它不仅考验着程序员的基础算法能力,还涉及到如何有效地利用数据结构来解决实际问题。接下来,我们将通过一个由浅入深的方式,详细解析这个问题,并给出相应的案例和代码实现。

问题描述

在"三数之和"问题中,给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c,使得 a + b + c = 0?找出所有满足条件且不重复的三元组。

简单解法 — 暴力法(不推荐)

一种最直观的方法是使用三重循环遍历所有可能的三元组组合,检查它们的和是否为 0。虽然这种方法简单直观,但其时间复杂度为 O(n^3),在数据量较大时会导致严重的性能问题。

代码实现

def three_sum_brute_force(nums):
    n = len(nums)
    result = []
    for i in range(n):
        for j in range(i+1, n):
            for k in range(j+1, n):
                if nums[i] + nums[j] + nums[k] == 0:
                    triplet = sorted([nums[i], nums[j], nums[k]])
                    if triplet not in result:
                        result.append(triplet)
    return result

高效解法 — 双指针法

为了优化算法,我们可以采用双指针法。首先对数组进行排序,然后使用一个固定指针遍历数组,对于每个固定指针的位置,使用两个指针(一个在固定指针之后,一个在数组末尾),通过移动这两个指针来搜索和为0的三元组。

解题步骤

  1. 排序:对数组进行排序。
  2. 遍历:固定一个数 nums[i],然后使用左右指针指向 nums[i] 后面的两端,数字分别为 nums[L] 和 nums[R],计算三个数的和 sum 判断是否满足条件。
  3. 去重:跳过重复的数字。

代码实现

def three_sum(nums):
    nums.sort()
    n, result = len(nums), []
    for i in range(n):
        if i > 0 and nums[i] == nums[i-1]:
            continue
        L, R = i+1, n-1
        while L < R:
            total = nums[i] + nums[L] + nums[R]
            if total < 0:
                L += 1
            elif total > 0:
                R -= 1
            else:
                result.append([nums[i], nums[L], nums[R]])
                while L < R and nums[L] == nums[L+1]:
                    L += 1
                while L < R and nums[R] == nums[R-1]:
                    R -= 1
                L += 1
                R -= 1
    return result

案例分析

假设输入数组为 nums = [-1, 0, 1, 2, -1, -4]

  1. 排序后的数组为 [-4, -1, -1, 0, 1, 2]
  2. 固定第一个数为 -4,在 -12 的范围内寻找两数之和为 4 的组合,不存在,移动固定数。
  3. 固定第二个数为第一个 -1,找到了两数之和为 1 的组合,即 [-1, 0, 1]
  4. 继续遍历,找到第二个组合为 [-1, -1, 2]

双指针法图解

给定一个数组nums = [-4, -1, -1, 0, 1, 2],目标是找出所有唯一的三元组,它们的和为0。

1. 排序

首先,对数组进行排序。

排序后的数组: [-4, -1, -1, 0, 1, 2]

2. 遍历和双指针搜索

对数组进行遍历,每次遍历中,固定一个元素,然后用两个指针在固定元素之后的数组部分进行搜索,一个指针从左向右移动(左指针),另一个从右向左移动(右指针)。

第一轮遍历

  • 固定元素: -4 (索引0)
  • 左指针: 在-1 (索引1)
  • 右指针: 在2 (索引5)
数组: [-4, -1, -1, 0, 1, 2]
固定元素: -4 (索引0)
左指针:    ↑ (索引1)
右指针:                  ↑ (索引5)

检查和调整

  • 第一次和为-4 + (-1) + 2 = -3 < 0,左指针向右移动。
  • 左指针移动到第二个-1处,和为-4 + (-1) + 2 = -3 < 0,左指针继续向右移动。
  • 左指针移动到0处,和为-4 + 0 + 2 = -2 < 0,左指针继续向右移动,直到左指针与右指针相遇,这轮遍历结束。

在这轮遍历中,没有找到和为0的三元组。

第二轮遍历

  • 固定元素变为: -1 (索引1)
  • 左指针: 在-1 (索引2)
  • 右指针: 在2 (索引5)
数组: [-4, -1, -1, 0, 1, 2]
固定元素: -1 (索引1)
左指针:        ↑ (索引2)
右指针:                  ↑ (索引5)

遍历的过程重复上述步骤,对每个固定元素,移动左右指针,并根据三数之和是大于还是小于0来调整指针的位置。

关键点

  • 当和小于0时,只移动左指针向右。
  • 当和大于0时,只移动右指针向左。
  • 当找到和为0的三元组时,记录下来,并同时移动左指针和右指针,寻找新的可能组合。

3. 去重

为了避免记录重复的三元组,每次在移动指针时,需要跳过重复的值。

结论

通过以上的解析和示例代码,我们可以看出,相比于暴力法,双指针法大大提高了"三数之和"问题的求解效率。


欢迎关注微信公众号 数据分析螺丝钉

相关文章
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
57 6
|
3月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
116 2
|
3月前
|
索引 Python
【Leetcode刷题Python】从列表list中创建一颗二叉树
本文介绍了如何使用Python递归函数从列表中创建二叉树,其中每个节点的左右子节点索引分别是当前节点索引的2倍加1和2倍加2。
61 7
|
3月前
|
算法 Python
【Leetcode刷题Python】 LeetCode 2038. 如果相邻两个颜色均相同则删除当前颜色
本文介绍了LeetCode 2038题的解法,题目要求在一个由'A'和'B'组成的字符串中,按照特定规则轮流删除颜色片段,判断Alice是否能够获胜,并提供了Python的实现代码。
51 3
|
3月前
|
算法 Python
【Leetcode刷题Python】剑指 Offer 33. 二叉搜索树的后序遍历序列
本文提供了一种Python算法,用以判断给定整数数组是否为某二叉搜索树的后序遍历结果,通过识别根节点并递归验证左右子树的值是否满足二叉搜索树的性质。
23 3
|
3月前
|
Python
【Leetcode刷题Python】50. Pow(x, n)
本文介绍了LeetCode第50题"Pow(x, n)"的解法,题目要求实现计算x的n次幂的函数,文章提供了递归分治法的详细解析和Python实现代码。
27 1
|
3月前
|
Python
【Leetcode刷题Python】LeetCode 478. 在圆内随机生成点
本文介绍了LeetCode 478题的解法,题目要求在给定圆的半径和圆心位置的情况下实现在圆内均匀随机生成点的功能,并提供了Python的实现代码。
31 1
|
3月前
|
算法 Python
【Leetcode刷题Python】295. 数据流的中位数
本文介绍了一种使用Python实现的数据结构,用以支持数据流中添加整数并返回当前所有元素的中位数,通过排序列表来计算中位数。
25 1
|
3月前
|
算法 Python
【Leetcode刷题Python】73. 矩阵置零
本文介绍了LeetCode第73题的解法,题目要求在给定矩阵中将所有值为0的元素所在的行和列全部置为0,并提供了一种原地算法的Python实现。
32 0
【Leetcode刷题Python】73. 矩阵置零
|
3月前
|
Python
【Leetcode刷题Python】1467. 两个盒子中球的颜色数相同的概率
本文介绍了LeetCode第50题"Pow(x, n)"的解法,题目要求实现计算x的n次幂的函数,文章提供了递归分治法的详细解析和Python实现代码。
43 0
下一篇
无影云桌面