Leetcode 剑指 Offer II 007. 数组中和为 0 的三个数

news2024/11/17 7:18:25

题目难度: 中等

原题链接

今天继续更新 Leetcode 的剑指 Offer(专项突击版)系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~

题目描述

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

  • 输入:nums = [-1,0,1,2,-1,-4]
  • 输出:[[-1,-1,2],[-1,0,1]]
  • 解释:
    • nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
    • nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
    • nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
    • 不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
    • 注意,输出的顺序和三元组的顺序并不重要。

示例 2:

  • 输入:nums = [0,1,1]
  • 输出:[]
  • 解释:唯一可能的三元组和不为 0 。

示例 3:

  • 输入:nums = [0,0,0]
  • 输出:[[0,0,0]]
  • 解释:唯一可能的三元组和为 0 。

提示:

  • 3 <= nums.length <= 3000
  • -10^5 <= nums[i] <= 10^5

题目思考

  1. 如何尽可能优化时间复杂度?

解决方案

思路

  • 分析题目, 最容易想到的做法就是暴力三重循环+集合去重: 遍历所有三个数字的组合, 找出和为 0 的, 再利用集合去重
  • 但这种做法时间效率太低 (O(N^3)), 如何优化呢?
  • 回顾上周的题目: Leetcode 剑指 Offer II 006. 排序数组中两个数字之和, 我们最终用 O(N) 的时间复杂度解决了『有序数组』两数之和为 target 的问题
  • 对这个问题来说, 如果我们先对数组排序, 然后固定第一个数字 a, 求剩下两个数的和为 -a 的组合, 是不是就能直接转换成那个问题了?
  • 这样时间复杂度就可以降低为 O(N^2) (排序预处理是 O(NlogN), 外层循环 a 需要 O(N), 内层求两数和也需要 O(N))
  • 具体双指针求和的思考过程大家可以参考上周的题解, 这里就不再赘述了
  • 不过这个问题多了去重的要求, 由于我们已经对数组进行了排序, 所以只需要比较相邻的数字, 具体做法如下:
    1. 针对第一个数字 a, 我们如果遇到多个连续相同的 a, 那么只有第一次才处理, 后面的直接跳过即可
    2. 针对后面两个数字 b 和 c, 我们找到一个满足条件的组合后, 先跟结果列表的最后一个组合比较, 如果两者相同, 说明是重复, 也跳过
  • 这还没完, 得益于数组的排序, 我们还可以进一步优化时间:
    1. 如果当前的 a 加上它后面紧挨着的两个数字已经超过 0, 就没必要继续遍历第一个数字大于等于 a 的任何其他组合了, 因为它们的和只会更大, 也即 break 外层循环
    2. 如果当前的 a 加上数组末尾的两个数字仍小于 0, 则没必要继续固定当前的 a 遍历 b 和 c 了, 因为它们的和只会更小, 也即 continue 外层循环
  • 下面代码中对上述每个步骤都有详细注释, 方便大家理解

复杂度

  • 时间复杂度 O(N^2): 排序 O(NlogN), 两重循环 O(N^2)
  • 空间复杂度 O(1): 只使用了几个常数空间的变量

代码

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        # 排序+三指针+两去重+两剪枝
        res = []
        # 先对数组进行排序, 从而可以使用j和k双指针求和
        nums.sort()
        n = len(nums)
        for i in range(n - 2):
            a = nums[i]
            if i > 0 and a == nums[i - 1]:
                # 去重1: 当前的a已经处理过了, 避免重复处理
                continue
            if a + nums[i + 1] + nums[i + 2] > 0:
                # 剪枝1: 相邻的三个数字之和已经大于0了, 后续更大于0, 直接break
                break
            if a + nums[-1] + nums[-2] < 0:
                # 剪枝2: 当前数字和最后两个数字之和仍小于0, 中间部分肯定更小于0, 继续遍历下一个i
                continue
            j, k = i + 1, n - 1
            while j < k:
                b, c = nums[j], nums[k]
                sm = a + b + c
                if sm == 0:
                    # 三数之和恰好等于0, 找到一个有效组合
                    # 左右指针同时向中间移动, 不再使用它们
                    i += 1
                    k -= 1
                    if res and res[-1] == [a, b, c]:
                        # 去重2: [a,b,c]组合已经添加到最终结果, 避免重复处理
                        # 注意由于数组有序, 所以已经存在的[a,b,c]一定是res列表的最后一个元素
                        continue
                    res.append([a, b, c])
                elif sm < 0:
                    # 三数之和小于0, 左指针右移
                    j += 1
                else:
                    # 三数之和大于0, 右指针右移
                    k -= 1
        return res

大家可以在下面这些地方找到我~😊

我的 GitHub

我的 Leetcode

我的 CSDN

我的知乎专栏

我的头条号

我的牛客网博客

我的公众号: 算法精选, 欢迎大家扫码关注~😊

算法精选 - 微信扫一扫关注我

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/113529.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信开放平台之第三方平台开发,从哪里入手?

大家好&#xff0c;我是悟空码字 疫情之下&#xff0c;最近有不少兄弟没有挺进决赛&#xff0c;半途成了小羊人&#xff0c;可谓是出师未捷身先死。话说回来&#xff0c;不管怎么样&#xff0c;尽量保护好自己&#xff0c;能越晚变羊越好。 开始说正事&#xff0c;不管是自己…

46_SDIO实验

目录 SDIO相关结构体 SDIO初始化结构体 SDIO命令初始化结构体 SDIO数据初始化结构体 硬件连接 实验源码 SDIO相关结构体 标准库函数对SDIO外设建立了三个初始化结构体&#xff0c;分别为SDIO初始化结构体SDIO_InitTypeDef, SDIO命令初始化结构体SDIO_CmdInitTypeDef和SD…

小技巧2:Python 实现阿拉伯数字转化为中文数字

大家好&#xff0c;我是Kamen Black君&#xff0c;今天给大家介绍一个小技巧&#xff1a;如何用Python 代码实现阿拉伯数字转化为中文数字。 都说光阴似箭&#xff0c;日月如梭&#xff0c;2022年的车轮很快也要驶向了终点。不知道大家在平常的生活中&#xff0c;有没有碰到过…

【Python】Beta分布详解

投硬币&#xff0c;硬币是正还是反&#xff0c;这属于两点分布的问题。 疯狂投硬币&#xff0c;正面出现的次数&#xff0c;服从二项分布&#xff1a;【Python】从二项分布到泊松分布 二项分布中&#xff0c;若特定时间内的伯努利试验次数趋于无穷大&#xff0c;那么在某一时…

【Linux】进程控制(进程创建、进程终止、进程等待、进程替换)

文章目录一、进程创建1.1 认识系统调用 fork1.2 理解 fork 的返回值1.3 写时拷贝策略二、进程终止2.1 main 函数的返回值2.2 进程退出的几种情况(&#x1f31f;)2.3 进程退出码2.4 终止正常进程&#xff1a;return、exit、_exit ⭐2.5 站在 OS 角度&#xff1a;理解进程终止三、…

RV1126笔记二十:吸烟行为检测及部署<七>

若该文为原创文章,转载请注明原文出处。 部署到RV1126,Demo测试 一、介绍 通过训练转换后,得到了RKNN模型,接下来使用rknn_model_zoo里自带的C demo来测试模型是不是可以在RV1126上运行。 C demo直接编译是编译不过的,需要自己移植. 根据C demo提供的README,可以看出…

7段数码管和打印机接口

目录 七段发光二级管显示器接口&#xff08;重点&#xff09; 打印机适配器&#xff08;重点&#xff09; 例题 补充两个芯片(了解&#xff09; 数据输出寄存器 数据输入三态缓冲器 七段发光二级管显示器接口&#xff08;重点&#xff09; 灯泡的题最难就是7段数码管。重点…

【Web开发】Python实现Web服务器(Ubuntu下调试Flask)

&#x1f37a;基于Python的Web服务器系列相关文章编写如下&#x1f37a;&#xff1a; &#x1f388;【Web开发】Python实现Web服务器&#xff08;Flask快速入门&#xff09;&#x1f388;&#x1f388;【Web开发】Python实现Web服务器&#xff08;Flask案例测试&#xff09;&a…

工厂卖家如何借助TikTok突围?

众所周知&#xff0c;TikTok已然成为全球最受欢迎的社交媒体之一&#xff0c;拥有巨大的流量池&#xff0c;对于跨境电商卖家来说&#xff0c;TikTok也是最大的站外流量来源。作为月活跃用户接近16亿的应用程序&#xff0c;TikTok的发展速度让很多社交媒体平台望尘莫及&#xf…

node.js+uni计算机毕设项目基于微信小程序寸金校园租车平台(程序+小程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等…

rabbitmq基础6——交换器和队列web监控基础运维、备份交换机、消息确认机制、消息状态查看

文章目录一、交换器和队列的使用1.1 web监控创建交换器1.1.1 交换器参数1.1.2 备份交换器1.1.2.1 工作原理1.1.2.2 弊端情形1.2 web监控创建队列1.2.1 队列参数1.2.1.1 通用参数1.2.1.2 其他参数1.2.1.2.1 所有队列1.2.1.2.2 主队列1.2.1.2.3 仲裁队列1.2.1.2.4 流队列1.3 web监…

从原理和源码梳理Springboot FatJar 的机制

一、概述 SpringBoot FatJar 的设计&#xff0c;打破了标准 jar 的结构&#xff0c;在 jar 包内携带了其所依赖的 jar 包&#xff0c;通过 jar 中的 main 方法创建自己的类加载器&#xff0c;来识别加载运行其不规范的目录下的代码和依赖。 二、标准的 jar 包结构 打开 Java…

用html实现一个静态登陆页面-可根据需求更改样式

一、创建html文件&#xff0c;vscode下载相关插件 我们先选择一个文件夹创建login.html&#xff0c;.之前的文件命无所谓&#xff0c;.之后就必须为html或者htm。 在编辑改文件输入!且出现提示后按回车或按tab快捷生成基础代码。 然后我们下载一个可以方便我们开发的插件。 …

【计算机网络课程设计】TCP协议包自动生成工具【蒙混过关版】

文章目录引言设计要求分工安排文献查阅总体设计流程具体设计内容&#x1f315;博客x主页&#xff1a;己不由心王道长&#x1f315;! &#x1f30e;文章说明&#xff1a;TCP协议包自动生成工具&#x1f30e; ✅系列专栏&#xff1a;计算机网络 &#x1f334;本篇内容&#xff1a…

Linux系统基础——系统调用

Linux系统调用 特此说明: 刘超的趣谈linux操作系统是比较重要的参考资料&#xff0c;本文大部分内容和所有图片来源于这个专栏。 1 相关概念 程序vs进程vs命令: Linux系统上所有的操作由进程完成&#xff0c;进程的运行是动态的&#xff0c;在此之前是一个静态的程序。用户用一…

2年过去了,有谁还记得曾想取代Node.js的他?

大家好&#xff0c;我卡颂。 22年11月14日&#xff0c;Deno发布了v1.28&#xff0c;距离他第一个稳定版本v1.0.0发布&#xff08;2020年5月13日&#xff09;已过去2年。 作为Node.js的竞争者&#xff0c;Deno似乎并没有达到取代前者的目标。 甚至&#xff0c;他在前端社区的…

离散数学数理逻辑部分【1】

前言 本文创作的起因是&#xff0c;经历了离散数学的学习&#xff0c;深感学习离散之艰辛。所以产生了写一些内容帮助大家期末复习。虽然在csdn发表本文&#xff0c;有些不太合适&#xff0c;但是还是相信本文的质量和内容&#xff0c;可以给正在学习离散数学的大学生提供一些…

【数据结构】—— 队列(有序队列及环形队列的数组实现)

目录 队列的一个使用场景 什么是队列&#xff1f; 数组模拟队列 实现思路&#xff1a; 编写一个ArrayQueue类的代码实现过程 判断队列是否满和空 入队出队 显示队列数据 问题 用数组模拟队列你会发现使用一次之后就不能使用了 &#xff0c;没有达到复用的效果。 数组…

yolov5s融合SPD-Conv用于提升小目标和低分辨率图像检测性能实践五子棋检测识别

今天刚发表的一篇论文提出来了针对小目标和低分辨率图像检测性能提升的技术SPD-Conv&#xff0c;感觉还是挺有意义的&#xff0c;今天主要是基于这项技术融合进yolov5s模型中来开发对应的目标检测模型&#xff0c;实现五子棋的检测&#xff0c;本身五子棋就是比较密集的小目标检…

RV1126笔记十五:吸烟行为检测及部署<二>

若该文为原创文章,转载请注明原文出处。 PC下yolov5环境搭建 我使用的训练环境是Windows10+MiniConda 接下来记录搭建全过程 备注:条件允许就使用ubuntu物理机,最好要有显卡,训练有显卡速度会快很多,没有显卡,训练300轮,亲测大概40小时,不值得。 一、miniconda 安装…