每日一题:LeetCode-LCR 007. 三数之和
每日一题系列(day 18)
前言:
🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈
🔎🔎如果说代码有灵魂,那么它的灵魂一定是👉👉算法👈👈,因此,想要写出💚优美的程序💚,核心算法是必不可少的,少年,你渴望力量吗😆😆,想掌握程序的灵魂吗❓❗️那么就必须踏上这样一条漫长的道路🏇🏇,我们要做的,就是斩妖除魔💥💥,打怪升级!💪💪当然切记不可😈走火入魔😈,每日打怪,拾取经验,终能成圣🙏🙏!开启我们今天的斩妖之旅吧!✈️✈️
题目:
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a ,b ,c ,使得 a + b + c = 0 ?请找出所有和为 0 且 不重复 的三元组。
示例:

提示:
- 0 <= nums.length <= 3000
- -105 <= nums[i] <= 105
解法一:暴力枚举
首先分析题目,题目让我们返回一个或多个不同的三元组,可以不用考虑顺序,但是不能有两组三元组都是相同元素,那么首先我们考虑暴力枚举策略:
先将数组排个序,以便于更好的查看重复的三元组,之后再使用三层for循环将所有情况都枚举出来,判断是否是符合条件的三元组,如果是,组成一维数组尾插进二维数组res中,当遍历完了之后使用set进行去重即可。
class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {if(nums.size() < 3)return {};sort(nums.begin(), nums.end());vector<vector<int>> res;int n = nums.size();for(int i = 0 ; i < n - 2 ; i++){for(int j = i + 1 ; j < n - 1 ; j++){for(int k = j + 1 ; k < n ; k++){if((nums[i] + nums[j] + nums[k]) == 0){res.push_back(vector<int>{nums[i], nums[j], nums[k]});}}}}set<vector<int>> uniq(res.begin(), res.end());res.assign(uniq.begin(), uniq.end());return res;}
};


测试用例可以通过,但是提交却发现还有三个测试用例跑不过,这时我们就要另想他法了。
解法二:双指针解法
我们还可以在暴力的基础上使用双指针解法,我们首先定住一个值,然后使用双指针来标记另外两个值,定住的值不动,双指针遍历剩下的数组元素,找出所有正确的三元组,尾插进二维数组里,数组遍历完,定值再向右遍历,双指针重置。这样循环上述步骤,就可以得到所有三元组,具体的步骤:
1、数组元素个数不满三个的直接返回空数组。创建二维数组用来存放三元组,为了更方便识别相同的三元组,我们将数组的值排个序。
2、固定一个值,在固定值后一个位置设置左指针,最后一个元素下标设为右指针,将固定值使用变量target记录。
3、而题目要求我们三元组的和为0,也就是要我们固定值和左右指针指向的值和为0,又数组是升序数组,如果target的值大于0了,则左右指针的值肯定也会>0,所以固定值一定要保证小于0。
4、固定值选取后,开始用双指针对数组剩下的元素进行遍历了,使用变量sum记录下左右指针指向元素的和,用来与target的值进行比较。
5、如果sum的值要大于target,说明右指针大了,数组为升序数组,则右指针向左移一位,再次进行比较。而如果sum的值小于target,说明左指针小了,将左指针右移一位,再次进行比较。
6、如果sum的值等于target的值,那么表示此时的左右指针加上固定值,就是一个符合规矩的三元组,将此三元组合并为一个一维数组尾插进二维数组ans数组中。
7、题目的测试用例说明了不能有重复的三元组出现,那么我们就需要进行去重操作,那么什么情况下才会有重复元素出现呢?
【1】当固定值不变的时候,左指针的的下一个位置的值和上一个位置的值相等,再次进行比较,就是一个新的三元组,但是这个三元组的值和上一个三元组的值就重复了,不仅左指针如此,右指针也是如此,所以需要将左右指针指向和上一个值不同的值。
【2】当固定值改变的时候,当数组遍历完,固定值需要更新,如果新固定值的值和原来的值相同,那么这组数据便利出来的三元组就和上组数据便利出来的三元组重复了,所以固定值也需要指向新的不重复的值。
代码演示:
class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {if(nums.size() < 3)//不满一个三元组return {};vector<vector<int>> ans;//二维数组sort(nums.begin(), nums.end());//将数据进行排序int n = nums.size();for(int i = 0 ; i < n;)//固定一个数,然后使用双指针进行三元组比较{if(nums[i] > 0) break;//target的值若>0,而数组又是升序,则后面的数一定也是大于0的int left = i + 1, right = n - 1, target = -nums[i];//左指针为i的下一个位置,右指针为最后一个位置,target为i位处与左右指针相加进行比较的元素while(left < right){int sum = nums[left] + nums[right];//记录左右指针相加的值if(sum > target) right --;//用sum和target值进行比较,>0时说明右指针太大了else if(sum < target) left ++;//<0,说明左指针太小了else//等于0,是符合条件的三元组{ans.push_back({nums[left], nums[right], nums[i]});//将符合条件的三元组尾插进数组left ++;//左右指针都移动一位right --;//去重操作while(left < right && nums[left] == nums[left - 1]) left ++;//如果左指针下一个值和前一个值相等,则得到的是重复的三元组,为了去重,将左指针向后移动,且要保证左指针小于右指针防止越界while(left < right && nums[right] == nums[right + 1]) right--;//同理,右指针的值也要保证和上一个右指针的值不同,且要保证右指针不越界}}++i;//这时上一个i的情况已经全部枚举完了,i指向数组的下一个位置while(i < n && nums[i] == nums[i - 1]) i++;//同理,i的下一个位置和上一个位置传的值如果是相同的,那么就会发生重复的三元组,为了去重,将i自增至于上一个i的值不同的位置}return ans;//返回二维数组}
};


这个双指针解法和我们前面写过的类似,可以先看看这题再来做我们说的这道题,思路就会很清晰了:查找总价格为目标值的两个商品
相关文章:
每日一题:LeetCode-LCR 007. 三数之和
每日一题系列(day 18) 前言: 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🔎…...
四元数傅里叶变换(Quaternion Fourier Transforms) 在信号和图像处理中的应用
引言: 信号和图像处理是现代科学和工程领域中非常重要的一个方向,它涉及到对信号和图像进行分析、压缩、增强和恢复等操作。传统的信号和图像处理方法主要依赖于傅里叶变换和滤波器等工具,但这些方法在处理复杂系统时存在一定的局限性。近年来,四元数傅里叶变换作为一种新兴…...
vue项目之.env文件.env.dev、test、pro
.env文件是vue运行项目时的环境配置文件。 .env: 全局默认配置文件,所有环境(开发、测试、生产等)均会加载并合并该文件 .env.development(开发环境默认命名) 开发环境的配置,文件名默认为.env.development,如果需要改名也是可以的…...
Fabric2.2:在有系统通道的情况下搭建应用通道
写在最前 在使用Fabric-SDK-Go1.0.0操作Fabric网络时遇到了bug。Fabric-SDK-GO的当前版本没有办法在没有系统通道的情况下创建应用通道,而Fabric的最新几个版本允许在没有系统通道的情况下搭建应用通道。为了解决这个矛盾并使用Fabric-SDK-GO完成后续的项目开发&…...
测试人员必备基本功(2)
容易被忽视的bug 第二章 修改表单容易被忽视的bug 文章目录 容易被忽视的bug第二章 修改表单容易被忽视的bug 前言一、修改表单二、具体功能1.修改角色2.接口设计 三、测试设计1.测试点2.容易发现bug的测试点如下: 总结 前言 一个WEB系统的所有功能模块࿰…...
第十二章 Java内存模型与线程(一)
文章目录 12.3 Java内存模型12.3.1 主内存与工作内存12.3.2 内存间交互操作小结12.3.3 对于volatile型变量的特殊规则12.3.5 原子性、可见性与有序性12.3.6 先行发生原则 12.3 Java内存模型 12.3.1 主内存与工作内存 1.Java 内存模型规定了所有的变量都存储在主内存ÿ…...
C# WPF 数据绑定
需求 后台变量发生改变,前端对应的相关属性值也发生改变 实现 接口 INotifyPropertyChanged 用于通知客户端(通常绑定客户端)属性值已更改。 示例 示例一 官方示例代码如下 using System; using System.Collections.Generic; using System.ComponentModel; using Sys…...
进程和线程的比较
目录 一、前言 二、Linux查看进程、线程 2.1 Linux最大进程数 2.2 Linux最大线程数 2.3 Linux下CPU利用率高的排查 三、线程的实现 四、上下文切换 五、总结 一、前言 进程是程序执行相关资源(CPU、内存、磁盘等)分配的最小单元,是一…...
深入理解 Flink(四)Flink Time+WaterMark+Window 深入分析
Flink Window 常见需求背景 需求描述 每隔 5 秒,计算最近 10 秒单词出现的次数 —— 滑动窗口 每隔 5 秒,计算最近 5 秒单词出现的次数 —— 滚动窗口 关于 Flink time 种类 TimeCharacteristic ProcessingTimeIngestionTimeEventTime WindowAssign…...
科技创新领航 ,安川运动控制器为工业自动化赋能助力
迈入工业4.0时代,工业自动化的不断发展,让高精度运动控制成为制造业高质量发展的重要技术手段。北京北成新控伺服技术有限公司作为一家集工业自动化产品销售、系统设计、开发、服务于一体的高新技术企业,其引进推出的运动控制产品一直以卓越的…...
图像异或加密及唯密文攻击
异或加密 第一种加密方式为异或加密,异或加密的原理是利用异或的可逆性质,原始图像的像素八位bit分别与伪随机二进制序列异或,得到的图像就为加密图像。如下图对lena图像进行加密。 伪随机序列为一系列二进制代码,它受加密秘钥控…...
React Grid Layout基础使用
摘要 React Grid Layout是一个用于在React应用程序中创建可拖拽和可调整大小的网格布局的库。它提供了一个灵活的网格系统,可以帮助开发人员构建响应式的布局,并支持拖拽、调整大小和动画效果。本文将介绍如何使用React Grid Layout来创建自适应的布局。…...
第11章 1 文件及IO操作
文章目录 文件的概述及基本操作步骤 p151文件的写入操作 p152文件的读取操作及文件复制 p153文件的读取操作文件复制 with语句的使用 p154一维数据和二维数据的存储与读取 p155高维数据的存储和读取 p156os模块中的常用的函数 p157os.path模块中常用的函数 p158 文件的概述及基…...
Tomcat服务实例部署
目录 **Tomcat 由一系列的组件构成,其中核心的组件有三个:** 什么是 servlet? 什么是 JSP? Tomcat 功能组件结构: Container 结构分析: Tomcat 请求过程: ## Tomcat 服务部署 1.关闭防火墙…...
高精度彩色3D相机:开启崭新的彩色3D成像时代
3D成像的新时代 近年来,机器人技术的快速发展促使对3D相机技术的需求不断增加,原因在于,相机在提高机器人的性能和实现多种功能方面发挥了决定性作用。然而,其中许多应用所需的解决方案更复杂,仅提供环境的深度信息是…...
借助Gitee将typora图片上传CSDN
概述 前面已经发了一个如何借助Github将typora上的图片上传到csdn上,但这有个缺陷:需要科学上网才能加速查看已经上传到github上的图片,否则就会出现已经上传的图片,无法正常查看的问题 如何解决? 那就可以使用Gite…...
几件奇怪的事产生的疑团
1.记得当年在中国科技大学杨照华给我们上初等数论课(杨是北大毕业,闵嗣鹤教授的关门弟子,后来到华南师大任教),他说过“据华老(华罗庚)讲,希尔伯特最先解决华林问题的论文中用到二十…...
陶瓷碗口缺口检测-图像增强
图像增强 在采集图像的过程中,可能会有由于采集图像环境中光源照射不足,导致采集的图像对比度不足,图像视觉效果较暗的情况,可以通过直方图均衡化或者直方图规定化。如图a为原图像对比度低,图c为其直方图,…...
gitee创建远程仓库并克隆远程仓库到电脑
1、首先点加号新建一个仓库 2、输入仓库名,路径会自动填充,填写简单的仓库介绍,先选择私有,在仓库创建之后,可以改为开源 3、打开建好的仓库 4、复制仓库链接 5、打开一个文件夹(想要存储远程仓库的地址),在…...
3D人体姿态估计(教程+代码)
3D人体姿态估计是指通过计算机视觉和深度学习技术,从图像或视频中推断出人体的三维姿态信息。它是计算机视觉领域的一个重要研究方向,具有广泛的应用潜力,如人机交互、运动分析、虚拟现实、增强现实等。 传统的2D人体姿态估计方法主要关注通…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...
从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
认识CMake并使用CMake构建自己的第一个项目
1.CMake的作用和优势 跨平台支持:CMake支持多种操作系统和编译器,使用同一份构建配置可以在不同的环境中使用 简化配置:通过CMakeLists.txt文件,用户可以定义项目结构、依赖项、编译选项等,无需手动编写复杂的构建脚本…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...
Monorepo架构: Nx Cloud 扩展能力与缓存加速
借助 Nx Cloud 实现项目协同与加速构建 1 ) 缓存工作原理分析 在了解了本地缓存和远程缓存之后,我们来探究缓存是如何工作的。以计算文件的哈希串为例,若后续运行任务时文件哈希串未变,系统会直接使用对应的输出和制品文件。 2 …...
