双指针算法详解(含力扣和蓝桥杯例题)
目录
一、双指针算法核心概念
二、常用的双指针类型:
2.1 对撞指针
例题1:盛最多水的容器
例题2:神奇的数组
2.2 快慢指针:
例题1:移动零
例题2:美丽的区间(蓝桥OJ1372)
3.总结:
一、双指针算法核心概念
双指针算法(Two Pointers)是一种通过两个指针协同遍历数据结构的优化技巧,常用于数组、链表等线性结构的场景,通过减少循环嵌套次数将时间复杂度从O(n²)优化至O(n)(有时候也有可能是O(n³)优化至O(n²))。其核心思想是通过指针的移动规则和终止条件设计,高效解决特定问题。
二、常用的双指针类型:
(1)对撞指针
(2)快慢指针
2.1 对撞指针
指的是两个指针left和right(简写为l和r)分别指向序列的第一个元素和最后一个元素。
然后在条件为l<r(也有可能是l<=r)时,为什么
对撞指针一般用来解决有序数组或者字符串问题(常见于区间问题):
查找有序数组中满足某些约束条件的一组元素问题:比如二分查找、数字之和等问题。
字符串反转问题:反转字符串、回文数、颠倒二进制等问题。
例题1:盛最多水的容器
11. 盛最多水的容器 - 力扣(LeetCode)
这道题需要我们明白两个点:
1.当条件相同时,长方形的长越大,面积越大
2.长方形的高由短的那一边决定
所以我们可以发现一个技巧,我们在每一个改变双指针的时候,都应该去改变高度比较短的那一边,这样我们就可以找到更长的高,也就可以找到最大的矩阵值。
代码如下:
class Solution {
public:int maxArea(vector<int>& height) {// 在同等条件下,长方形的长越大,面积越大// 长方形的高是由比较短的那一边决定的int l = 0, r = height.size() - 1;int ans = 0;while(l < r){// 遍历左指针和右指针int num = min(height[l], height[r]);ans = max(ans, num * (r - l)); // 更新面积的最大值if(height[l] <= height[r]){ // 查看是否有更大的值l++;}else{r--; }}return ans;}
};
例题2:神奇的数组
链接如下:
蓝桥账户中心
首先这道题就是需要使用对撞指针让我们逐个遍历,并使用前缀和用来后面获得每一个子区间的前缀和和异或前缀和,代码如下:
/** @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git* @Date: 2025-03-19 08:20:27* @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git* @LastEditTime: 2025-03-19 15:18:52* @FilePath: \VSCode\神奇的数组.cpp* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE*/
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
const int N = 2e5 + 20;
ll a[N] = { 0 }, prefix[N] = { 0 }, yh[N] = { 0 }; // 定义原数组,前缀和数组以及异或前缀和数组int main() {cin.tie(nullptr);cout.tie(nullptr);ios::sync_with_stdio(0);int n;cin >> n;for (int i = 1; i <= n; i++) {cin >> a[i]; prefix[i] = prefix[i - 1] + a[i]; // 求前缀和yh[i] = yh[i - 1] ^ a[i]; // 求异或前缀和}// 开始计算组合数ll ans = 0;for (int right = 1, left = 1; right <= n; right++) { // 定义好左指针以及右指针// 这里请注意比较运算符的优先级比算数低,所以我们计算出前缀和的时候,一定要加上括号// (prefix[right] - prefix[left - 1] != yh[right] ^ yh[left - 1])会被解析为:// ((prefix[right] - prefix[left - 1]) != yh[right]) ^ yh[left - 1],这显然是不行的。while (left <= right && (prefix[right] - prefix[left - 1]) != (yh[right] ^ yh[left - 1])) {left++;}ans += (right - left + 1); // 如果符合要求,就添加进去}cout << ans << endl;return 0;
}
2.2 快慢指针:
快慢指针简介:
快慢指针一般比对撞指针更难想,也更难写,指的是两个指针侧开始遍历序列,且移动的步长一慢一快。快的指针被称为快指针,移动慢的指针被称为慢指针。为了方便理解,我们称快指针为r,慢指针为l,这样慢指针和快指针构成区同。两个指针以不同速度、不同策略移动,直到快指针移动到数组尾端,或者两指针相交,或者满足其他特殊条件时为止。
快慢指针解题方法:
1.使用两个指针1、r。1一般指向序列第一个元素,即:1=1,r一般指向序列第零个元素(用来给子区间初始化用的),即:r=0。即初始时区间[, rl=[1,0]表示为空区间。
2.在循环体中将左右指针向右移动。当满足一定条件时,将慢指针右移,即l++。当满足另
外一定条件时(也可能不需要满足条件),将快指针右移,即r++,保持[l,r]为合法区间。
3.到指针移动到数组尾端(即l=n且r==n),或者两指针相交,或者满足其他特殊条件时跳
出循环体。
例题1:移动零
283. 移动零 - 力扣(LeetCode)
解题思路(这些思路是看网上的大神写的):
这道题就是创建两个指针i和j,在第一次遍历的时候,我们需要让j来记录当前有多少个非0的数字,如果当前数字不是0的话,执行nums[j++] = nums[i];这样我们就可以保证当数字为0的时候,j指针停了下来,直到我们找到了又一个非0的数字为止。遍历完之后,j就是最后一个非0数字在数组上的位置。然后进行第二次遍历,让j后面的数字全部设置为0就可以了,因为非零的数字已经统计完了。
代码如下:
class Solution {public void moveZeroes(int[] nums) {if(nums==null) {return;}//第一次遍历的时候,j指针记录非0的个数,只要是非0的统统都赋给nums[j]int j = 0;for(int i=0;i<nums.length;++i) {if(nums[i]!=0) {nums[j] = nums[i];j++;}}//非0元素统计完了,剩下的都是0了//所以第二次遍历把末尾的元素都赋为0即可for(int i=j;i<nums.length;++i) {nums[i] = 0;}}
}
也可以写成这个样子,更加的简洁:
class Solution {
public:void moveZeroes(vector<int>& nums) {int slow = 0;for (int i = 0; i < nums.size(); i++) {if (nums[i] != 0) {// 每次保证是0和非0的交换swap(nums[slow++], nums[i]);}}}
};
例题2:美丽的区间(蓝桥OJ1372)
蓝桥账户中心
这道题就是需要我们使用枚举+双指针的思想,我们需要在保持左指针不变的情况下,遍历不同的右指针找到最美丽的区间(也就是区间和sum大于题目所给的值s,并且区间也是最小)。并且要记得更新最小的值。
代码如下:
#include<iostream>
using namespace std;
const int N = 1e5;
int a[N];
int main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int n, s, sum = 0; // n为数组大小,s为目标值,sum为当前和cin >> n >> s;for(int i = 1; i <= n; i++){cin >> a[i];}int ans = n + 1; // 记录答案for(int r = 0, l = 1; l <= n; l++){ // 开始遍历快慢指针while(l > r || r + 1 <= n && sum < s){ // 左指针固定,右指针向右移动r++;sum += a[r]; // 右指针向右移动,增加当前和}if(sum >= s){// 如果当前的和大于等于目标值,更新答案ans = min(ans, r - l + 1);}sum -= a[l]; // 左指针向右移动,减少当前和}if(ans==n+1) cout<<0;else cout<<ans;return 0;}
3.总结:
双指针一般是由快慢指针和对撞指针这两部分组成,其中快慢指针一般是比对撞指针要难一些,我们需要通过题目的意思来设置合适的条件。然后枚举每一种情况就行。
写在最后:
我们可以在这里学习C++知识:
0voice · GitHub
相关文章:

双指针算法详解(含力扣和蓝桥杯例题)
目录 一、双指针算法核心概念 二、常用的双指针类型: 2.1 对撞指针 例题1:盛最多水的容器 例题2:神奇的数组 2.2 快慢指针: 例题1:移动零 例题2:美丽的区间(蓝桥OJ1372) 3.总…...

【网络编程】二、UDP网络套接字编程详解
文章目录 前言Ⅰ. UDP服务端一、服务器创建流程二、创建套接字 -- socketsocket 属于什么类型的接口❓❓❓socket 是被谁调用的❓❓❓socket 底层做了什么❓❓❓和其函数返回值有没有什么关系❓❓❓ 三、绑定对应端口号、IP地址到套接字 -- bind四、数据的发送和接收 -- sendto…...

【应急响应】- 日志流量如何分析?
【应急响应】- 日志流量如何下手?https://mp.weixin.qq.com/s/dKl8ZLZ0wjuqUezKo4eUSQ...
虚拟机设置NAT没网笔记
查看任务管理器的时候发现,VMware NAT Service 进程都没有,貌似是因为之前我给禁了,emmmmmm 1确认虚拟机网络设置的NAT模式 打开 VMware Workstation,点击 编辑 > 虚拟网络编辑器 确保 VMnet8 配置为 NAT 模式: …...

djinn: 3靶场渗透
djinn: 3 来自 <https://www.vulnhub.com/entry/djinn-3,492/> 1,将两台虚拟机网络连接都改为NAT模式 2,攻击机上做namp局域网扫描发现靶机 nmap -sn 192.168.23.0/24 那么攻击机IP为192.168.23.182,靶场IP192.168.23.243 3࿰…...

VS Code配置指南:打造高效的QMK开发环境
VS Code配置指南:打造高效的QMK开发环境 前言 你是否曾为QMK固件开发环境的搭建而头疼不已?本文将手把手教你使用Visual Studio Code(简称VS Code)这款强大的代码编辑器来构建一个完美的QMK开发环境,让你的键盘固件开…...

服务器多客户端连接核心要点(1)
刷题 服务器多客户端连接核心要点 多进程服务器 实现原理 fork子进程:每次accept新客户端后,调用fork创建子进程。独立处理:子进程负责与客户端通信(如read/write),父进程继续监听新连接。 特点 隔离性…...
【Python-Day 11】列表入门:Python 中最灵活的数据容器 (创建、索引、切片)
Langchain系列文章目录 01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…...

Stagehand:AI驱动的下一代浏览器自动化框架
Stagehand 是一个结合了 AI 代理、AI 工具和 Playwright 的浏览器自动化框架。核心理念是:让自动化任务既可控又智能。与传统工具不同,Stagehand 不仅仅依赖 AI 代理的“黑箱操作”,而是通过与 Playwright 的深度结合,赋予开发者对…...
实现线程的4种方法
知识点详细说明 在Java中,实现线程的常用方法有以下四种: 1. 继承Thread类 核心要点: 定义一个类继承Thread,重写run()方法。通过调用start()启动线程(自动执行run())。关键细节: 单继承限制:Java不支持多继承,若类已继承其他类,无法再继承Thread。线程对象直接使用…...

爱普生FA-238在车身控制模块中的应用
在汽车智能化、电子化飞速发展的当下,车身控制模块(BCM)作为车辆的 “智能管家”,肩负着协调和控制众多车身功能的重任,从车门的解锁与锁定、车窗的升降,到车灯的智能点亮与熄灭,再到雨刮器的自…...
单片机嵌入式按键库
kw_btn库说明 本库主要满足嵌入式按键需求,集成了常用的按键响应事件:高电平、低电平、上升沿、下降沿、单击、双击、长按键事件。可以裸机运行,也可以配合实时操作系统运行。 本库开源连接地址:连接 实现思路 本库采用C语言进行…...

【A2A】管中窥豹,google源码python-demo介绍
前言 A2A(Agent2Agent)是 Google 推出的一项新协议,旨在解决多智能体(Multi-Agent)系统中跨平台、跨组织协作的难题。它为 AI 代理之间的通信、协作和任务分工提供了一个统一的标准,可以类比为网页世界的 H…...

004-nlohmann/json 快速认识-C++开源库108杰
了解 nlohmann/json 的特点;理解编程中 “数据战场”划分的概念;迅速上手多种方式构建一个JSON对象; 1 特点与安装 nlohmann/json 是一个在 github 长期霸占 “JSON” 热搜版第1的CJSON处理库。它的最大优点是与 C 标准库的容器数据…...

Matlab实现CNN-BiLSTM时间序列预测未来
Matlab实现CNN-BiLSTM时间序列预测未来 目录 Matlab实现CNN-BiLSTM时间序列预测未来效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现CNN-BiLSTM时间序列预测未来; 2.运行环境Matlab2023b及以上,data为数据集,单变量时间序…...

C语言| sizeof(array)占多少字节
C语言| 数组名作为函数参数 sizeof(数组名); 可以求出整个数组在内存中所占的字节数。 被调函数Array_Sum()中,数组array使用sizeof会得到多少? 实参数组a占32字节,实参a传给形参array,只占4字节。 原因如下: 数组名做…...

【文件系统—散列结构文件】
文章目录 一、实验目的实验内容设计思路 三、实验代码实现四、总结 一、实验目的 理解linux文件系统的内部技术,掌握linux与文件有关的系统调用命令,并在此基础上建立面向随机检索的散列结构文件;## 二、实验内容与设计思想 实验内容 1.设…...

World of Warcraft [CLASSIC][80][Deluyia] [Fragment of Val‘anyr]
瓦兰奈尔的碎片 [Fragment of Valanyr] 有时候下个班打个游戏,没想到套路也这么多,唉,何况现实生活,这一个片版本末期才1000G,30个,也就30000G,时光徽章等同月卡15000G,折合一下也就…...

数组和指针典型例题合集(一维数组、字符数组、二维数组)
1.一维数组 数组名的理解 数组名是数组首元素(第一个元素)的地址 但是有两个例外: 1.sizeof (数组名)—— 数组名表示整个数组,就算的是整个数组的大小,单位是字节。 2.&数组名 —— 数…...

地级市-机器人、人工智能等未来产业水平(2009-2023年)-社科数据
地级市-机器人、人工智能等未来产业水平(2009-2023年)-社科数据https://download.csdn.net/download/paofuluolijiang/90623814 https://download.csdn.net/download/paofuluolijiang/90623814 此数据集统计了2009-2023年全国地级市在机器人、人工智能等…...

epub格式转txt格式工具,txt批量转PDF
epub格式转txt格式工具,功能如图: txt格式批量转PDF 参考原文:epub格式转txt格式工具,txt批量转PDF 轻轻一点就关注, 好运连连挡不住,点个关注吧。...

电赛经验分享——模块篇
1、前言 打算在这一个专栏中,分享一些本科控制题电赛期间的经验,和大家共同探讨,也希望能帮助刚刚参加电赛的同学,了解一些基本的知识。一些见解和看法可能不同或有错误,欢迎批评指正。 在本文中,主要介绍笔…...
前端面试宝典---JavaScript import 与 Node.js require 的区别
import 和 require 来自不同的规范: import 是 ES6(ECMAScript 2015)模块系统的一部分,是 JavaScript 语言的标准语法 require 是 CommonJS 规范的一部分,最初为 Node.js 环境设计 加载方式: require() …...

JVM之内存管理(一)
部分内容来源:JavaGuide二哥Java 图解JVM内存结构 内存管理快速复习 栈帧:局部变量表,动态链接(符号引用转为真实引用),操作数栈(存储中间结算结果),方法返回地址 运行时…...

鸿蒙编译boost整合linux跨平台应用
openharmony deveco 4.1支持armeabi-v7a deveco 5.0后不支持arm32位系统 boost编译 使用deveco的写cmake集成boost boost使用1.88的最新版本,带cmake工具链 https://github.com/boostorg/boost.git boost的源码都在sub_module中 deveco 4.1的版本sdk最高到9&am…...

rabbitMQ消息问题与解决
rabbitMQ 消息顺序性、消息幂等性、消息不丢失、最终一致性、补偿机制、消息队列设计 1.消息顺序性 溯源: 消息队列中的若干消息如果是对同一个数据进行操作,这些操作具有前后的关系,必须要按前后的顺序执行,否则就会造成数据异常…...

Java SE(10)——抽象类接口
1.抽象类 1.1 概念 在之前讲Java SE(6)——类和对象(一)的时候说过,所有的对象都可以通过类来抽象。但是反过来,并不是说所有的类都是用来抽象一个具体的对象。如果一个类本身没有足够的信息来描述一个具体的对象,而…...
MySQL数据库故障排查与解决方案
一、故障排查流程图 #mermaid-svg-hF8hhP2lrqWDbNhV {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-hF8hhP2lrqWDbNhV .error-icon{fill:#552222;}#mermaid-svg-hF8hhP2lrqWDbNhV .error-text{fill:#552222;stroke:…...

学习threejs,使用Physijs物理引擎
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️Physijs 物理引擎1.1.1 ☘️…...

allure生成测试报告(搭配Pytest、allure-pytest)
文章目录 前言allure简介allure安装软件下载安装配置环境变量安装成功验证 allure运行流程allure装饰器函数基本说明装饰器函数使用allure.attach 命令行运行利用allure-pytest生成中间结果json 查看测试报告总览页面每个tab页的说明类别页面测试套图表页面时间刻度功能页面包 …...