基础算法--双指针

两数之和

点击:题目链接

 解法一:暴力解法

时间复杂度:O(N^2)

算法思路:两层for循环即可列出所有两个数字的组合,判断是否等于目标值

算法流程:

两层 for 循环: 外层 for 循环依次枚举第⼀个数 a ;

内层 for 循环依次枚举第⼆个数 b ,让它与 a 匹配;

ps :这⾥有个魔⻤细节:我们挑选第⼆个数的时候,可以不从第⼀个数开始选,因为 a 前 ⾯的数我们都已经在之前考虑过了;因此,我们可以从 a 往后的数开始列举。

然后将挑选的两个数相加,判断是否符合⽬标值。

class Solution {
public:vector<int> twoSum(vector<int>& price, int target) {int n = price.size();for(int a = 0;a<n;a++){for(int b = 1;b<n;b++){if(price[a]+price[b]==target){return {price[a],price[b]};}}}return{-1,-1};}
};

会超时

解法二:双指针 

时间复杂度:O(N)

算法思路: 注意到本题是升序的数组,因此可以⽤「对撞指针」优化时间复杂度。

算法流程(附带算法分析,为什么可以使⽤对撞指针):

a. 初始化 left,right 分别指向数组的左右两端(这里不是我们理解的指针,而是数组的下标)

b. 当 left < right 的时候,一直循环。
i. 当 nums [left] + nums [right] == target 时,说明找到结果,记录结果,并且返回;
ii. 当 nums [left] + nums [right] < target 时:

  • 对于 nums [left] 而言,此时 nums [right] 相当于 nums [left] 能碰到的最大值(别忘了,这里是升序数组哈~)。如果此时不符合要求,说明在这个数组里面,没有别的数符合 nums [left] 的要求了(最大的数都满足不了你,你已经没救了)。因此,我们可以大胆舍去这个数,让 left++,去比较下一组数据;
  • 那对于 nums [right] 而言,由于此时两数之和是小于目标值的,nums [right] 还可以选择比 nums [left] 大的值继续努力达到目标值,因此 right 指针我们按兵不动;
    iii. 当 nums [left] + nums [right] > target 时,同理我们可以舍去 nums [right](最小的数都满足不了你,你也没救了)。让 right--,继续比较下一组数据,而 left 指针不变(因为他还是可以去匹配 nums [right] 更小的数的)。

代码:

class Solution {
public:vector<int> twoSum(vector<int>& price, int target) {int left = 0,right = price.size()-1;while(left<right){if(price[left]+price[right]>target){right--;}    else if(price[left]+price[right]<target){left++;}else{return {price[left],price[right]};}}return{-1,-1};}
};

三数之和

点击:题目链接

算法思路:

本题与两数之和类似,是非常经典的面试题。

与两数之和稍微不同的是,题目中要求找到所有 “不重复” 的三元组。那我们可以利用在两数之和那里用的双指针思想,来对我们的暴力枚举做优化:
i. 先排序;
ii. 然后固定一个数 a:
iii. 在这个数后面的区间内,使用 “双指针算法” 快速找到两个数之和等于 -a 即可。

但是要注意的是,这道题里面需要有 “去重” 操作~
i. 找到一个结果之后,left 和 right 指针要 “跳过重复” 的元素;
ii. 当使用完一次双指针算法之后,固定的 a 也要 “跳过重复” 的元素。

这里算法思想不难,需要注意一些极端情况的处理,比如{0,0,0},这里需要处理好你的边界。

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {//先排序sort(nums.begin(),nums.end());//返回的是一个二维vector<vector<int>> vt;int i = 0,left = 1,right = nums.size()-1;//双指针for(i = 0;i<nums.size()-2;i++)//固定数a{if(nums[i]>0){break;//小优化}left = i+1;right = nums.size()-1;while(left<right){if(nums[left]+nums[right]>-nums[i]){right--;}else if(nums[left]+nums[right]<-nums[i]){left++;}else if(nums[left]+nums[right]==-nums[i]){vt.push_back({ nums[i],nums[left],nums[right] });//去重//考虑相同数字,只能单边跳,不要两边一起跳,否则会少算一些组合//注意left+1可能越界while(left<right&&nums[left]==nums[left+1]){left++;}//right-1同理while(left<right&&nums[right]==nums[right-1]){right--;}left++;right--;}}//i+1也可能越界while(i<nums.size()-2&&nums[i+1]==nums[i]){i++;}}return vt;}
};

四数之和

点击:题目链接

算法思路: 和上题基本一样,不过这道题可能会有一点小坑,这里出现了4个数相加会大于INT_MAX的情况,所以需要处理一下,去重操作基本可上题一样。

a.依次固定⼀个数 a ;

b.在这个数 a 的后⾯区间上,利⽤「三数之和」找到三个数,使这三个数的和等于 target - a 即可。

class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {sort(nums.begin(),nums.end());vector<vector<int>> vt;int a,b,c,d;for(a=0;a<nums.size();a++){if(nums.size()<3){break;}for(b = a+1;b<nums.size()-2;b++){c = b+1;d = nums.size()-1;while(c<d){long max = (long)nums[c]+nums[d];if(nums[a]+nums[b]==target-max){vt.push_back({nums[a],nums[b],nums[c],nums[d]});while(c<d&&nums[c]==nums[c+1]){c++;}while(c<d&&nums[d]==nums[d-1]){d--;}c++;d--;}else if(nums[a]+nums[b]<target-max){c++;}else{d--;}}while(b<nums.size()-2&&nums[b]==nums[b+1]){b++;}}while(a<nums.size()-3&&nums[a]==nums[a+1]){a++;}}return vt;}
};

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

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

相关文章

什么是Linux系统架构?

​ Linux系统架构是指Linux操作系统的整体结构和工作层次&#xff0c;它定义了系统组件如何交互、如何管理硬件资源&#xff0c;以及用户如何通过不同的层次与系统进行交互。Linux架构通常有两种划分方法&#xff1a;系统层次架构和功能层次架构&#xff0c;两者都可以很好地描…

不是“我应该做什么”,而是“我想做什么”

1. 识别内心的渴望 首先&#xff0c;我们需要识别自己真正的愿望和激情所在。这可能需要一些时间和自我反思。问自己&#xff1a;在没有任何外界压力的情况下&#xff0c;我真正想做的是什么&#xff1f;是赚钱、生活、旅行、追星&#xff0c;还是其他什么&#xff1f;识别这些…

React第十七章(useRef)

useRef 当你在React中需要处理DOM元素或需要在组件渲染之间保持持久性数据时&#xff0c;便可以使用useRef。 import { useRef } from react; const refValue useRef(initialValue) refValue.current // 访问ref的值 类似于vue的ref,Vue的ref是.value&#xff0c;其次就是vu…

【C++】内存分布、new、delete、 operator new、operator delete

内存分布 在C语言和C中&#xff0c;程序内存被划分成六个部分&#xff1a; 内核空间、栈、内存映射段、堆、数据段、代码段 栈&#xff1a;又称堆栈&#xff0c;主要为非静态局部变量、函数参数、返回值等&#xff0c;栈的生长方向是向下生长的 内存映射段&#xff1a;高效的…

混合云策略在安全领域受到青睐

Genetec 发布了《2025 年物理安全状况报告》&#xff0c;该报告根据超过 5,600 名该领域领导者&#xff08;其中包括 100 多名来自澳大利亚和新西兰的领导者&#xff09;的回应&#xff0c;揭示了物理安全运营的趋势。 报告发现&#xff0c;澳大利亚和新西兰的组织采用混合云策…

FastAPI解决跨域报错net::ERR_FAILED 200 (OK)

目录 一、跨域问题的本质 二、FastAPI中的CORS处理 1. 安装FastAPI和CORS中间件 2. 配置CORS中间件 3. 运行FastAPI应用 三、解决跨域报错的步骤 四、案例:解决Vue.js与FastAPI的跨域问题 1. Vue.js前端应用 2. FastAPI后端API 3. 配置CORS中间件 4. 运行和测试 五…

霍尔效应电流传感器

适用于大电流&#xff0c;低功耗的电流检测&#xff1a; TVS选型: RS232的隔离电路: 单片机采集200伏高压 如何做隔离电路&#xff1a; 采用线性光电耦合器HCNR200实现高压直流母线电压的精确采样。还是用电阻分压&#xff0c;只是在ADC检测阶段加上隔离芯片&#xff1a;

【计网笔记】习题

物理层 不属于物理层接口规范定义范畴的是&#xff08;C&#xff09; A. 接口形状 B. 引脚功能 C. 物理地址 D. 信号电平 【2023-912】光网络只能通过导向型介质传播。&#xff08;&#xff09; 【2017-408】若信道在无噪声情况下的极限数据传输速率不小于信噪比为30dB条件下的…

最新 AI 编程工具全面对比:v0、Bolt.new、Cursor、Windsurf

随着人工智能的快速发展&#xff0c;越来越多的 AI 驱动的开发工具应运而生&#xff0c;旨在提升开发效率、优化开发流程&#xff0c;并减轻开发者的工作负担。在这个背景下&#xff0c;四款新兴的 AI 编程工具&#xff1a;v0、Bolt.new、Cursor 和 Windsurf&#xff0c;各具特…

【C++算法】35.位运算_两整数之和

文章目录 题目链接&#xff1a;题目描述&#xff1a;解法C 算法代码&#xff1a; 题目链接&#xff1a; 371. 两整数之和 题目描述&#xff1a; 解法 笔试的话直接 return ab&#xff1b; 接下来讲一下这题的解法&#xff1a; 位运算&#xff08;异或运算-无进位相加&#xff…

PyCharm+Selenium+Pytest配置小记

1、下载ChromeDriver&#xff1a; Chrome130以后的Driver下载&#xff1a; Chrome for Testing availabilityhttps://googlechromelabs.github.io/chrome-for-testing/ &#xff08;1&#xff09;查看自己Crome浏览器的版本&#xff1a;设置-->关于 Chrome&#xff1b; &…

如何在UI自动化测试中创建稳定的定位器?

如何在UI自动化测试中创建稳定的定位器&#xff1f; 前言1. 避免使用绝对路径2. 避免在定位器中使用索引3. 避免多个类名的定位器4. 避免动态和自动生成的ID5. 确保定位器唯一6. 处理隐藏元素的策略7. 谨慎使用基于文本的定位器8. 使用AI创建稳定的定位器 总结 前言 在自动化测…

明日宣讲 香港科技大学广州|数据科学与分析学域硕博招生宣讲会【湖南大学专场】

&#x1f4e3;&#x1f4e3;&#x1f4e3;明日宣讲 香港科技大学广州&#xff5c;数据科学与分析学域硕博招生宣讲会【湖南大学专场】 时间&#xff1a;2024年12月10日&#xff08;星期二&#xff09;15:00 地点&#xff1a;湖南大学信息科学与工程学院624会议室 报名链接&…

BurpSuite-8(FakeIP与爬虫审计)

声明&#xff1a;学习视频来自b站up主 泷羽sec&#xff0c;如涉及侵权马上删除文章 感谢泷羽sec 团队的教学 视频地址&#xff1a;IP伪造和爬虫审计_哔哩哔哩_bilibili 一、FakeIP 1.配置环境 BurpSuite是java环境下编写的&#xff0c;而今天的插件是python编写的&#xff0c…

Qt C++ 显示多级结构体,包括结构体名、变量名和值

文章目录 mainwindow.hmainwindow.cppstructures.hmain.cpp QTreeView 和 QStandardItemModel 来实现。以下是实现这一功能的步骤和示例代码&#xff1a; 定义多级结构体&#xff1a; 假设你有一个多级结构体&#xff0c;如下所示&#xff1a; struct SubStruct {int subValue…

linux基于systemd自启守护进程 systemctl自定义服务傻瓜式教程

系统服务 书接上文: linux自启任务详解 演示系统:ubuntu 20.04 开发部署项目的时候常常有这样的场景: 业务功能以后台服务的形式提供,部署完成后可以随着系统的重启而自动启动;服务异常挂掉后可以再次拉起 这个功能在ubuntu系统中通常由systemd提供 如果仅仅需要达成上述的场…

ros项目dual_arm_pick-place(moveit和gazebo联合仿真)(一)

目录 前言正文创建功能包具体代码运行 总结 前言 dual_arm_pick-place项目中&#xff0c;实现了两套的moveit和gazebo联合仿真。 启动文件分别是bringup_moveit.launch和arm_bringup_moveit.launch。 在这个项目中&#xff0c;我将代码重新创建了一个包&#xff0c;co_simula…

MySQL 索引(B+树)详解

MySQL 索引&#xff08;B树&#xff09;详解 MySQL逻辑架构对比InnoDB与MyISAM存储结构存储空间可移植性、备份及恢复事务支持AUTO_INCREMENT表锁差异全文索引表主键表的具体行数CRUD操作外键 sql优化简介什么情况下进行sql优化sql语句执行过程sql优化就是优化索引 索引索引的优…

MySQL生产环境备份脚本

全量备份脚本&#xff0c;其中BakDir&#xff0c;ZlbakDir&#xff0c;LogFile需要自己创建 #!/bin/bash export LANGen_US.UTF-8# 指定备份目录 BakDir/root/beifen/data/mysqlbak/data/allbak # 指定增量备份目录 ZlbakDir/root/beifen/data/mysqlbak/data/zlbak # 备份日志…

HTTP multipart/form-data 请求

序言 最近在写项目的过程中有一个需求是利用 HTTP 协议传输图片和视频&#xff0c;经过查询方法相应的方法发现使用 multipart/form-data 的方式&#xff0c;这是最常见处理二进制文件的表单编码类型。  学习了一下午&#xff0c;现在总结一下使用的方法和相关的知识点&#x…