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

C++ 优先算法 —— 三数之和(双指针)

目录

题目:三数之和 

1. 题目解析

2. 算法原理

①.  暴力枚举

②.  双指针算法

不漏的处理:

 去重处理:

 固定一个数 a 的优化:

3. 代码实现

Ⅰ.  暴力枚举(会超时 O(N³))

Ⅱ.  双指针算法 (O(N²))


题目:三数之和 

1. 题目解析

题目截图:

 

题目中所述的顺序不重要有两种情况:

  1. 最终选出来的几个三元组里,每个三元组里的数据顺序,是可以不用考虑的。
  2. 最终选出来的几个三元组,三元组的顺序,也是可以不用考虑的。

题目中还要求元素不能相同:

 

 

题目的细节要求也就是:

  • 最终选出来的几个三元组里面的元素是对应不同的 
  • 返回的三元组及其三元组里的数据的顺序不重要。 

  

题目给的示例二就是没有最终结果的情况

 

2. 算法原理

这道题有两种解法:

  • 暴力枚举(但会超时)
  • 双指针算法

①.  暴力枚举

虽然暴力枚举会超时,这里还要介绍一下的,因为双指针解法就是基于暴力枚举进行优化的。

这里方法就是:排序+暴力枚举(从左往右)+去重

 这里排序去重要注意的是:

所以可以换个策略,先对原数组整个排序:

所以,也就是先排序,再暴力枚举(从左往右枚举),再去重。

这样套三个for循环就可以暴力枚举结果了

//伪代码演示
for (int i = 0; i < n;) // 固定一个数a
{for (int j = i + 1; j < n;)     //依次固定枚举第二个数{for (int k = j + 1; k < n;)    //枚举第三个数{//查找符合的三元组,去重...}}}

 (这里去重在下面双指针解法解释),这里套了三个for循环时间复杂度:O(N³)。

②.  双指针算法

这里双指针算法的解决方法就是:排序+双指针+去重

排序同上面暴力枚举,都先对一整个数组排序,再进行下面的处理。

这里举例一个已经排过序的新数组:

我们先固定一个数,这里先固定第一个数:

这里就转化成了和为s的两个数的问题,这里的s就是这个固定的数的相反数。也就是:

 所以这里解决步骤:

  1. 先对整个数组排序
  2. 固定一个数 a(这里有个小优化,后续介绍)
  3. 在该数后面的区间内,利用双指针算法快速找到两个数的和为 -a 的即可。

注意:这里只是找到了符合条件的情况,并没有去重。

接下来就是处理细节问题了,也就是去重确保所有符合条件的情况不落下(后面简称不漏) 。

和为s的两个数(这里会用到,详细介绍在此链接)

不漏的处理:

先控制指针找到符合情况:

这时可以看到是找到符合的情况了: 接下来就需要调整:

所以,也就是找到一种结果之后,不要停(两个指针不停),缩小区间(两指针都向内移动一步),继续寻找符合的情况。

 去重处理:

去重要考虑两种情况:

  1. 找到一种结果之后,left和right指针要跳过重复的元素(这里也就把第一个4给枚举完了)。但这里固定的 a 还是为-4,再继续枚举,是肯定都是重复结果的。
  2. 所以当使用完一次双指针算法后,a也需要跳过重复的元素。

这里去重可能指针会越界,为了避免越界:

这里的越界问题不止对整个数组区间的越界,还有对要用双指针处理的区间可能会越界。

在实现去重代码时需要加个判断条件就可以解决:

要判断处理这个条件,既可避免越界
if(left < right)        
也就判断两个指针是否在相遇前

 固定一个数 a 的优化:

因为我们前面先排序该数组为升序了,所以固定数a就可以仅仅需要保证它≤0即可。 

if (nums[i] > 0)
{break; // 小优化,数a为正数情况不用考虑,是一定不成立的
}

 接下来实现代码。

3. 代码实现

题目链接:三数之和

Ⅰ.  暴力枚举(会超时 O(N³))

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {// 1.排序sort(nums.begin(), nums.end());vector<vector<int>> ret; // 用来存储所有的三元组// 2.暴力枚举int n = nums.size();int i, j, k;for (i = 0; i < n;) // 固定一个数a{for (j = i + 1; j < n;)     //依次固定枚举第二个数{for (k = j + 1; k < n;)    //枚举第三个数{int sum = nums[i] + nums[j] + nums[k];if (sum == 0){ret.push_back({ nums[i],nums[j],nums[k] });}//去重++k;while (k < n && nums[k] == nums[k - 1]) {++k;}}//去重++j;while (j < n && nums[j] == nums[j - 1]) {++j;}}//去重++i;while (i < n && nums[i] == nums[i - 1]) {++i;}}return ret;}
};

提交记录:

测试用例:

 

 

 

 

Ⅱ.  双指针算法 (O(N²))

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {// 1.排序sort(nums.begin(), nums.end());vector<vector<int>> ret; // 用来存储所有的三元组// 2.利用双指针解决int n = nums.size();for (int i = 0; i < n;) // 固定一个数a{if (nums[i] > 0) {break; // 小优化,数a为正数情况不用考虑,是一定不成立的}// 定义left,right,target通过双指针获取相加等于0的组合int left = i + 1, right = n - 1, target = -nums[i];while (left < right) {int sum = nums[left] + nums[right];if (sum > target) {--right;} else if (sum < target) {++left;} else {// 将获取的三元组尾插ret里ret.push_back({nums[i], nums[left], nums[right]});// 将所有的情况获取--不漏,并去重// 缩小区间查找++left;--right;// 去重left和right,注意区间越界问题while (left < right && nums[left] == nums[left - 1]) {++left;}while (left < right && nums[right] == nums[right + 1]) {--right;}}}// 注意去重i++i;while (i < n && nums[i] == nums[i - 1]) {++i;}}return ret;}
};

注:这里时间复杂度是O(N²)。 

提交记录:

 

 制作不易,若有不足之处或出问题的地方,请各位大佬多多指教 ,感谢大家的阅读支持!!!  

 

相关文章:

C++ 优先算法 —— 三数之和(双指针)

目录 题目&#xff1a;三数之和 1. 题目解析 2. 算法原理 ①. 暴力枚举 ②. 双指针算法 不漏的处理&#xff1a; 去重处理&#xff1a; 固定一个数 a 的优化&#xff1a; 3. 代码实现 Ⅰ. 暴力枚举&#xff08;会超时 O&#xff08;N&#xff09;&#xff09; Ⅱ.…...

YOLOv7-0.1部分代码阅读笔记-yolo.py

yolo.py models\yolo.py 目录 yolo.py 1.所需的库和模块 2.class Detect(nn.Module): 3.class IDetect(nn.Module): 4.class IAuxDetect(nn.Module): 5.class IBin(nn.Module): 6.class Model(nn.Module): 7.def parse_model(d, ch): 8.if __name__ __main__…...

【缓存与加速技术实践】Web缓存代理与CDN内容分发网络

文章目录 Web缓存代理Nginx配置缓存代理详细说明 CDN内容分发网络CDN的作用CDN的工作原理CDN内容的获取方式解决缓存集中过期的问题 Web缓存代理 作用&#xff1a; 缓存之前访问过的静态网页资源&#xff0c;以便在再次访问时能够直接从缓存代理服务器获取&#xff0c;减少源…...

MySQL的约束和三大范式

一.约束 什么是约束&#xff0c;为什么要用到约束&#xff1f; 约束就是用于创建表时&#xff0c;给对应的字段添加对应的约束 约束的作用就是当我们用insert into时&#xff0c;如果传入的数据有问题&#xff0c;不符合创建表时我们定的规定&#xff0c;这时MySQL就会自动帮…...

Unity网络通信(part7.分包和黏包)

目录 前言 概念 解决方案 具体代码 总结 分包黏包概念 分包 黏包 解决方案概述 前言 在探讨Unity网络通信的深入内容时&#xff0c;分包和黏包问题无疑是其中的关键环节。以下是对Unity网络通信中分包和黏包问题前言部分的详细解读。 概念 在网络通信中&#xff0c;…...

练习题 - DRF 3.x Overviewses 框架概述

Django REST Framework (DRF) 是一个强大的工具,用于构建 Web APIs。作为 Django 框架的扩展,DRF 提供了丰富的功能和简洁的 API,使得开发 RESTful Web 服务变得更加轻松。对于想要在 Django 环境中实现快速且灵活的 API 开发的开发者来说,DRF 是一个非常有吸引力的选择。学…...

Linux 经典面试八股文

快速鉴别十个题 1&#xff0c;你如何描述Linux文件系统的结构&#xff1f; 答案应包括对/, /etc, /var, /home, /bin, /lib, /usr, 和 /tmp等常见目录的功能和用途的描述。 2&#xff0c;在Linux中如何查看和终止正在运行的进程&#xff1f; 期望的答案应涵盖ps, top, htop, …...

Filter和Listener

一、Filter过滤器 1 概念 可以实现拦截功能&#xff0c;对于指定资源的限定进行拦截&#xff0c;替换&#xff0c;同时还可以提高程序的性能。在Web开发时&#xff0c;不同的Web资源中的过滤操作可以放在同一个Filter中完成&#xff0c;这样可以不用多次编写重复代码&#xf…...

Go 项目中实现类似 Java Shiro 的权限控制中间件?

序言&#xff1a; 要在 Go 项目中实现类似 Java Shiro 的权限控制中间件&#xff0c;我们可以分为几个步骤来实现用户的菜单访问权限和操作权限控制。以下是一个基本的实现框架步骤&#xff1a; 目录 一、数据库设计 二、中间件实现 三、使用中间件 四、用户权限管理 五…...

【Javascript】-一些原生的网页设计案例

JavaScript 网页设计案例 1. 动态时钟 功能描述&#xff1a;在网页上显示一个动态更新的时钟&#xff0c;包括小时、分钟和秒。实现思路&#xff1a; 使用 setInterval 函数每秒更新时间。获取当前时间并更新页面上的文本。 代码示例&#xff1a;<div id"clock"…...

SpringBoot开发——Spring Boot 3种定时任务方式

文章目录 一、什么是定时任务二、代码示例1、 @Scheduled 定时任务2、多线程定时任务3、基于接口(SchedulingConfigurer)实现动态更改定时任务3.1 数据库中存储cron信息3.2 pom.xml文件中增加mysql依赖3.3 application.yaml文件中增加mysql数据库配置:3.4 创建定时器3.5 启动…...

Flutter鸿蒙next 实现长按录音按钮及动画特效

在 Flutter 中实现长按录音按钮并且添加动画特效&#xff0c;是一个有趣且实用的功能。本文将通过实现一个具有动画效果的长按录音按钮&#xff0c;带领你一步步了解如何使用 Flutter 完成这个任务&#xff0c;并解释每一部分的实现。 一、功能需求 我们需要一个按钮&#xf…...

【计网】实现reactor反应堆模型 --- 框架搭建

没有一颗星&#xff0c; 会因为追求梦想而受伤&#xff0c; 当你真心渴望某样东西时&#xff0c; 整个宇宙都会来帮忙。 --- 保罗・戈埃罗 《牧羊少年奇幻之旅》--- 实现Reactor反应堆模型 1 前言2 框架搭建3 准备工作4 Reactor类的设计5 Connection连接接口6 回调方法 1 …...

力扣中等难度热题——长度为K的子数组的能量值

目录 题目链接&#xff1a;3255. 长度为 K 的子数组的能量值 II - 力扣&#xff08;LeetCode&#xff09; 题目描述 示例 提示&#xff1a; 解法一&#xff1a;通过连续上升的长度判断 Java写法&#xff1a; C写法&#xff1a; 相比与Java写法的差别 运行时间 时间复杂…...

JSON格式

JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;易于人和机器阅读和解析。它基于JavaScript的对象表示法&#xff0c;但被广泛用于多种编程语言。 JSON中的数据类型 字符串&#xff08;String&#xff09;&#xff1a;用双引…...

O-RAN前传Spilt Option 7-2x

Spilt Option 7-2x 下行比特处理上行比特处理相关文章&#xff1a; Open Fronthaul wrt ORAN 联盟被称为下层拆分(LLS)&#xff0c;其目标是提高电信市场的灵活性和竞争力。下层拆分是指无线电单元(RU) 和分布式单元(DU) 之间的拆分。 O-RAN前传接口可以在 eCPRI 上传输。eCPR…...

【GeoJSON在线编辑平台】(2)吸附+删除+挖孔+扩展

前言 在上一篇的基础上继续开发&#xff0c;补充上吸附功能、删除矢量、挖孔功能。 实现 1. 吸附 参考官方案例&#xff1a;Snap Interaction 2. 删除 通过 removeFeature 直接移除选中的要素。 3. 挖孔 首先是引入 Turf.js &#xff0c;然后通过 mask 方法来实现挖孔的…...

确定图像的熵和各向异性 Halcon entropy_gray 解析

1、图像的熵 1.1 介绍 图像熵&#xff08;image entropy&#xff09;是图像“繁忙”程度的估计值&#xff0c;它表示为图像灰度级集合的比特平均数&#xff0c;单位比特/像素&#xff0c;也描述了图像信源的平均信息量。熵指的是体系的混乱程度&#xff0c;对于图像而言&#…...

大数据-214 数据挖掘 机器学习理论 - KMeans Python 实现 算法验证 sklearn n_clusters labels

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…...

算法通关(3) -- kmp算法

KMP算法的原理 从题目引出 有两个字符串s1和s2,判断s1字符串是否包含s2字符串&#xff0c;如果包含返回s1包含s2的最左开头位置&#xff0c;不包含返回-1&#xff0c;如果是按照暴力的方法去匹配&#xff0c;以s1的每个字符作为开头&#xff0c;用s2的整体去匹配&#xff0c;…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...

数据库正常,但后端收不到数据原因及解决

从代码和日志来看&#xff0c;后端SQL查询确实返回了数据&#xff0c;但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离&#xff0c;并且ai辅助开发的时候&#xff0c;很容易出现前后端变量名不一致情况&#xff0c;还不报错&#xff0c;只是单…...

32位寻址与64位寻址

32位寻址与64位寻址 32位寻址是什么&#xff1f; 32位寻址是指计算机的CPU、内存或总线系统使用32位二进制数来标识和访问内存中的存储单元&#xff08;地址&#xff09;&#xff0c;其核心含义与能力如下&#xff1a; 1. 核心定义 地址位宽&#xff1a;CPU或内存控制器用32位…...