当前位置: 首页 > news >正文

力扣题目解析--三数之和

题目

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != 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
  • -105 <= nums[i] <= 105

代码展示 

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>> result;sort(nums.begin(), nums.end()); // 对数组进行排序for (int i = 0; i < nums.size() - 2; i++) {if (i > 0 && nums[i] == nums[i - 1]) continue; // 跳过重复元素int left = i + 1, right = nums.size() - 1;while (left < right) {int sum = nums[i] + nums[left] + nums[right];if (sum < 0) {left++; // 和太小,增加左边的数} else if (sum > 0) {right--; // 和太大,减少右边的数} else {// 找到一个解result.push_back({nums[i], nums[left], nums[right]});while (left < right && nums[left] == nums[left + 1]) left++; // 跳过重复的左指针while (left < right && nums[right] == nums[right - 1]) right--; // 跳过重复的右指针left++;right--;}}}return result;}
};

写者心得 

对于这一道题目,我刚开始的想法就是用一个循环,再加上一个超长的if循环解决这个问题。可是刚一开始调试if循环的条件就报了错。在学习请教的过程中,我觉得这个代码有着以下的几个亮点:

1.在设定动态数组的时候,使用二维数组。(我刚开始接触这个题目的时候,我所设定的数组并没有考虑到二维数组。而题目要求的那个结果却是二维数组,没有认出来,这是我学识上的不足。)

2.代码的第二步就对数组进行了排序(一步的目的其实是为了之后使用双指针做铺垫,,但是在我刚开始对于题目思考的时候,也根本没有考虑到先将元素进行排序之后,更容易得到数组前后两个数的和是否为0)

3.如果在if循环中条件过多,就应该考虑使用while循环。(他说了我刚开始就是给if循环里面加了一大堆条件,事实证明这样的路是走不通的。如果以后遇到了多条件的题目的时候,就应该考虑使用while循环,而不是在if循环里不断套用。)

4.双指针,它的精髓在于在数组中找三个数和为零的数字(我在之前的编程中其实使用过双指针,但是那时候我看的不太懂。现在我可以总结出双指针使用的情况,应该就在于与前后两个数有关系的时候,双指针能发挥很大的作用。)

5.跳过重复元素。(这一步看似平平无奇,但其实是使用双指针至关重要的前提,试想一下,如果遇到重复的元素,其输出的结果会对于我们对于整个代码的逻辑产生非常严重的影响。而且,这样的困扰会一直伴随着我们对于代码的读写和思考)

6.去重(这一点是我根本就没有想到的,或者说我的思路还没有到这一步,但是代码用了两个while循环,轻松解决了在得到目标数组之后,如果在二维数组中这个数组与其他的数组重复的时候的问题。)

 

代码解释 

定义和初始化

vector<vector<int>> result;

这行代码创建了一个空的二维向量 result。每个内部的 vector<int> 将会保存一个三元组。

添加元素

当你找到一个满足条件的三元组时,你可以将其添加到 result 中:

result.push_back({nums[i], nums[left], nums[right]});

这里的 {nums[i], nums[left], nums[right]} 是一个初始化列表,它会被转换成一个 vector<int> 并添加到 result 的末尾。

sort(nums.begin(), nums.end()); // 对数组进行排序

使用 sort 函数对输入数组 nums 进行升序排序。排序后,可以通过双指针法有效地查找满足条件的三元组。

for (int i = 0; i < nums.size() - 2; i++) {

开始一个外层循环,遍历数组中的每一个元素,作为第一个数 nums[i]。这里 i 的范围是从 0nums.size() - 3,因为还需要两个额外的位置来放置另外两个数。

if (i > 0 && nums[i] == nums[i - 1]) continue; // 跳过重复元素

如果当前元素 nums[i] 与前一个元素相同,则跳过本次循环,避免产生重复的三元组。

int left = i + 1, right = nums.size() - 1;

初始化两个指针 leftright,分别指向当前元素 nums[i] 后的第一个位置和数组的最后一个位置。

while (left < right) {

进入一个内层循环,当 left 指针小于 right 指针时继续循环。

int sum = nums[i] + nums[left] + nums[right];

计算当前三个指针所指向的元素之和 sum

if (sum < 0) {left++; // 和太小,增加左边的数

如果 sum 小于零,说明当前和太小,需要增大 left 指针所指向的数,因此将 left 向右移动一位。

} else if (sum > 0) {right--; // 和太大,减少右边的数

如果 sum 大于零,说明当前和太大,需要减小 right 指针所指向的数,因此将 right 向左移动一位。

} else {// 找到一个解result.push_back({nums[i], nums[left], nums[right]});

如果 sum 等于零,说明找到了一个满足条件的三元组,将其添加到结果列表 result 中。

while (left < right && nums[left] == nums[left + 1]) left++; // 跳过重复的左指针

为了避免产生重复的三元组,如果 left 指针所指向的数与下一个数相同,则继续将 left 向右移动。

while (left < right && nums[right] == nums[right - 1]) right--; // 跳过重复的右指针

同理,如果 right 指针所指向的数与前一个数相同,则继续将 right 向左移动。

left++;
right--;

无论是否有重复的数,都需要将 leftright 指针各向中间移动一位,以便继续查找新的可能的三元组。

return result;

返回结果列表 result,其中包含了所有满足条件的三元组。

 

相关文章:

力扣题目解析--三数之和

题目 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 示…...

qt QTabWidget详解

1、概述 QTabWidget是Qt框架中的一个控件&#xff0c;它提供了一个标签页式的界面&#xff0c;允许用户在不同的页面&#xff08;或称为标签&#xff09;之间切换。每个页面都可以包含不同的内容&#xff0c;如文本、图像、按钮或其他小部件。QTabWidget非常适合用于创建具有多…...

linux shell脚本学习(1):shell脚本基本概念与操作

1.什么是shell脚本 linux系统中&#xff0c;shell脚本或称之为bash shell程序&#xff0c;通常是由vim编辑&#xff0c;由linux命令、bash shell指令、逻辑控制语句、注释信息组成的可执行文件 *linux中常以.sh后缀作为shell脚本的后缀。linux系统中文件乃至脚本的后缀并没有…...

Savitzky-Golay(SG)滤波器

Savitzky-Golay&#xff08;SG&#xff09;滤波器是一种在时域内基于局域多项式最小二乘法拟合的滤波方法&#xff0c;它最初由Savitzky A和Golay M于1964年提出&#xff0c;并广泛应用于数据流平滑除噪。 基本介绍 一、基本原理 SG滤波器通过在滑动窗口内拟合多项式来平滑数…...

Webserver(2.7)共享内存

目录 共享内存共享内存实现进程通信 共享内存 共享内存比内存映射效率更高&#xff0c;因为内存映射关联了一个文件 共享内存实现进程通信 write.c #include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include <string.h>int main(){…...

【网安案例学习】凭证填充Credential Stuffing

### 凭证填充的深入讨论 凭证填充&#xff08;Credential Stuffing&#xff09;是一种网络攻击技术&#xff0c;攻击者利用从数据泄露中获取的大量用户名和密码组合&#xff0c;尝试在其他网站和服务上进行自动化登录。这种攻击依赖于用户在多个网站上重复使用相同密码的习惯。…...

网站建设公司怎么选?网站制作公司怎么选才不会出错?

寻找适合靠谱的网站设计公司&#xff0c;不要盲目选广告推最多的几家&#xff0c;毕竟要实现自身品牌营销&#xff0c;还是需要多方面考量。以下几个方面可以作为选择的参考&#xff1a; 1. 专业能力如何&#xff1f; 一个公司的专业能力&#xff0c;决定了最后网站设计的成果…...

19. 架构重要需求

文章目录 第19章 架构重要需求19.1 从需求文档中收集架构重要需求&#xff08;ASRs&#xff09;不要抱太大希望从需求文档中找出架构重要需求 19.2 通过访谈利益相关者收集架构重要需求19.3 通过理解业务目标收集架构重要需求19.4 在效用树中捕获架构重要需求19.5 变化总会发生…...

iOS 再谈KVC、 KVO

故事背景&#xff1a;大厂面试&#xff0c;又问道了基本的kvc kvo的原理和使用&#xff0c;由于转了前端&#xff0c;除了个setter和getter&#xff0c;我全忘记了&#xff0c;其实还是没有理解记忆&#xff0c;下面再看一下kvc 和kvo ,总结一个让人通过理解而无法忘记的方法&a…...

java、excel表格合并、指定单元格查找、合并文件夹

#创作灵感# 公司需求 记录工作内容 后端&#xff1a;JAVA、Solon、easyExcel、FastJson2 前端&#xff1a;vue2.js、js、HTML 模式1&#xff1a;合并文件夹 * 现有很多文件夹 想合并全部全部的文件夹的文件到一个文件夹内 * 每个部门发布的表格 合并全部的表格为方便操作 模…...

最基础版编译运行Java(纯小白)

流程图&#xff1a; ⚠ 需要先安装JDK (Java Development Kit) 1. 写文件 首先写好自己的“文件”&#xff0c;可以用Sublime Text等文本编辑器写&#xff0c;还可以直接新建文本文档写一个.txt文件。 以编写一个HelloWorld程序为例&#xff1a; public class HelloWorld{p…...

六西格玛项目助力,手术机器人零部件国产化稳中求胜——张驰咨询

项目背景 XR-1000型腔镜手术机器人是某头部手术机器人企业推出的高端手术设备&#xff0c;专注于微创手术领域&#xff0c;具有高度的精确性和稳定性。而XR-1000型机器人使用的部分核心零部件长期依赖进口&#xff0c;特别是高精度电机、关节执行机构和视觉系统等&#xff0c;…...

Python爬虫系列(一)

目录 一、urllib 1.1 初体验 1.2 使用urllib下载网页、图片、视频等 1.3 反爬介绍 1.4 请求对象定制 1.5 get请求的quote方法 1.6 多个参数转成ascii编码 1.7 post请求 1.8 综合案例演示 一、urllib 1.1 初体验 # urllib是python默认带的&#xff0c;无需额外下载 i…...

# vim那些事...... vim删除文件全部内容

vim那些事… vim删除文件全部内容 1、在 Vim 中删除整个文件的内容&#xff0c;可以使用以下命令&#xff1a; 1&#xff09;打开 Vim&#xff0c;并编辑你想要清空的文件。 2&#xff09;按 Esc 确保你不在插入模式&#xff0c;而在命令模式。 3&#xff09;输入 gg 跳转到…...

Selinux及防火墙

一&#xff0c;selinux简介&#xff1a; SELinux&#xff08;Security-Enhanced Linux&#xff09;是一个Linux内核安全模块&#xff0c;旨在提供强制访问控制&#xff08;MAC&#xff09;机制&#xff0c;以增强系统的安全性。由美国国家安全局&#xff08;NSA&#xff09;开…...

业绩代码查询实战——php

一、一级代码显示职员 foreach($data_职员信息 as $key > $value){//$where_查询分类$where_查询通用;//$dat分类one $业绩提成->where($where_查询分类)->order("CreateDate desc")->select();if($value[haschildname]0 && $value[key] !"…...

内网穿透技术选型PPTP(点对点隧道协议)和 FRP(Fast Reverse Proxy)

PPTP&#xff08;点对点隧道协议&#xff09;和 FRP&#xff08;Fast Reverse Proxy&#xff09;是两种实现内网穿透的技术&#xff0c;但它们的工作原理、使用场景和特点有很大区别。以下是它们的详细比较&#xff1a; PPTP&#xff08;Point-to-Point Tunneling Protocol&am…...

信号与噪声分析——第三节:随机过程的统计特征

随机过程的定义&#xff1a; 随机过程是一种数学模型&#xff0c;用来描述系统或现象在时间或者空间上随之变化的不确定性。 一个随机过程的数字特征 1.数学期望&#xff08;统计平均值&#xff09;&#xff1a; 表示为 数学期望是随机过程在时间 t 上的平均值&#xff0c;通常…...

nginx(四):如何在 Nginx 中配置以保留真实 IP 地址

如何在 Nginx 中配置以保留真实 IP 地址 1、概述2、nginx配置示例2.1、配置说明2.2、客户端获取真实IP2.2.1、代码说明 3、插曲4、总结 大家好&#xff0c;我是欧阳方超&#xff0c;可以我的公众号“欧阳方超”&#xff0c;后续内容将在公众号首发。 1、概述 当使用nginx作为…...

docker对nginx.conf进行修改后页面无变化或页面报错

可能是因为没有重启nginx容器 可以执行 docker restart nginx 重启nginx试试 引入了其他的配置文件 本人安装的是docker默认的nginx&#xff0c;自带了一个default.conf的配置文件&#xff0c;并且在nginx.conf中还引入了这个文件&#xff0c;后面我还对nginx.conf添加了一个…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...