数据结构与算法:双指针
前言
双指针其实和滑动窗口差不多,但能使用的场景比滑动窗口更广功能更强。滑动窗口的内容在我上一篇文章数据结构与算法:滑动窗口。
一、原理
双指针的关键还是分析题目单调性,从而保证指针可以单方向滑动。
二、题目
1.按奇偶排序数组 II
class Solution {
public:vector<int> sortArrayByParityII(vector<int>& nums) {int n=nums.size();for(int even=0,odd=1,i=n-1;even<n&&odd<n;){if(nums[i]%2==0){swap(even,i,nums);even+=2;}else {swap(odd,i,nums);odd+=2;}} return nums;}void swap(int a,int b,vector<int>&nums){int t=nums[a];nums[a]=nums[b];nums[b]=t;}
};
这个题还是比较简单的,设置两个指针分别指向奇数位置和偶数位置的思路很好想,重点是每次去看的位置。这里设置为只盯着数组最后一个数看,然后把这个数往前发送,就可以避免每次讨论指针该不该滑动的问题。
2.寻找重复数
class Solution {
public:int findDuplicate(vector<int>& nums) {//寻找链表入环节点int slow=nums[0];int fast=nums[nums[0]];while(slow!=fast){slow=nums[slow];fast=nums[nums[fast]];}fast=0;//头节点为0!nums[0]已经跳过一次while(slow!=fast){slow=nums[slow];fast=nums[fast];}return slow;}
};
这个题的思路就比较抽象了,首先考虑将数组的值看作链表的next指针,这样对用例画出链表的图后,会发现构成一个有环链表,所以考虑使用寻找有环链表的入环节点的快慢指针。
具体内容在我数据结构与算法:链表相关题目的文章中。
3.救生艇
class Solution {
public:int numRescueBoats(vector<int>& people, int limit) {//先排序sort(people.begin(),people.end());int n=people.size();int l=0,r=n-1;int ans=0;while(l<=r){int sum=l==r?people[l]:people[l]+people[r];if(sum>limit){r--;}else{l++;r--;}ans++;}return ans;}
};
这个题的分析感觉有点像贪心,因为只要体重超了就得多用一艘船,所以当两个人体重超了的时候,肯定优先给大体重的人分船,而小体重的人可能还能跟别人拼船。
所以考虑先将数组排序,之后在头尾设置两个指针,若超了,就只给最右侧大体重的人分船。注意临界情况,当只剩一个人时,需要多给一艘船。
4.盛最多水的容器
class Solution {
public:int maxArea(vector<int>& height) {int n=height.size();int l=0,r=n-1;int ans=0;while(l<r){ans=max(ans,min(height[l],height[r])*(r-l));if(height[l]<height[r]){l++;}else{r--;}}return ans;}
};
这个题就体现出分析题目单调性的重要了。分析题目,可以发现,水的体积和高度、长度之间都存在单调性关系,所以,同样在头尾设置两个指针,控制长度变量的单调性,接着根据两指针位置的高度,每次滑动较小高度的指针,即可保证高度变量的单调性。
具体分析就是,每次l到r范围上,水体积的最大值必然是此时l到r的距离乘以l和r的最小值。当l不动时,即水的高度由最小值l决定,由于r只能向左滑,所以距离必然减小。而无论r的高度增加与否,因为l不动,所以即使r的高度增大,水的高度仍然是两者最小值l。同理当r不动时情况类似。
5.供暖器
class Solution {
public:int findRadius(vector<int>& houses, vector<int>& heaters) {//先排序sort(houses.begin(),houses.end());sort(heaters.begin(),heaters.end());int ans=0;for(int i=0,j=0;i<houses.size();i++){while(!best(i,j,houses,heaters)){j++;}ans=max(ans,abs(heaters[j]-houses[i]));}return ans;}bool best(int i,int j,vector<int>&houses,vector<int>&heaters){return j==heaters.size()-1||abs(heaters[j]-houses[i])<abs(heaters[j+1]-houses[i]);}
};
这个题的重点还是单调性,从常理出发,一般都会想到先对两个数组排序。
之后就是单调性分析,因为要求加热半径最小,而两数组又有序,所以最小的加热半径就是每个房屋到最近的加热器距离的最大值。(我想不出更好的解释方法了,感觉靠的就是直觉和常识)
所以在两数组上分别设置一个指针,若该房屋到下一个加热器的距离更小,就跳到下一个加热器。注意这里若距离相等也要让j往下跳,不然j就会一直被锁死在这个地方。
6.接雨水
class Solution {
public:int trap(vector<int>& height) {return solve2(height);}int solve1(vector<int>&height){int n=height.size();vector<int>leftMax(n,0);leftMax[0]=height[0];vector<int>rightMax(n,0);rightMax[n-1]=height[n-1];for(int i=1;i<n;i++){leftMax[i]=height[i]>leftMax[i-1]?height[i]:leftMax[i-1];}for(int i=n-2;i>=0;i--){rightMax[i]=height[i]>rightMax[i+1]?height[i]:rightMax[i+1];}int ans=0;for(int i=0;i<n;i++){ ans+=max(0,min(leftMax[i],rightMax[i])-height[i]);}return ans;}//双指针优化int solve2(vector<int>&height){int n=height.size();int leftMax=height[0];int rightMax=height[n-1];int l=1,r=n-2;int ans=0;while(l<=r){if(leftMax>=rightMax){ans+=max(0,rightMax-height[r]);rightMax=max(rightMax,height[r--]);}else{ans+=max(0,leftMax-height[l]);leftMax=max(leftMax,height[l++]);}}return ans;}
};
这个题也是很经典的一道题了,感觉双指针的思路反而不太好想。
首先第一个思路就是纯暴力,因为每个位置的水量只取决于左右两侧最大值,所以先构建出左右两侧最大值的数组,之后逐一比较即可。
第二个方法就是双指针优化的解。和第四个题盛最多水的容器的单调性类似,只需要在头尾设置两个指针,然后再维护左右两侧最大值,最后每次结算最大值小的那侧即可。
7.缺失的第一个正数
class Solution {
public:int firstMissingPositive(vector<int>& nums) {int l=0;int r=nums.size();while(l<r){if(nums[l]==l+1){l++;}else if(nums[l]<=l||nums[l]>r||nums[nums[l]-1]==nums[l]){swap(l,--r,nums);}else{swap(l,nums[l]-1,nums);}}return l+1;}void swap(int a,int b,vector<int>&nums){int t=nums[a];nums[a]=nums[b];nums[b]=t;}
};
这个题就有点抽象了,这个思路根本不知道怎么想出来的。
首先分析题目,可以发现,数组长度为n,所以缺失的最小正整数一定在1~n+1之间。所以考虑在头尾设置两个指针,l表示左侧的数都已经处在该在的位置,即不缺失,r表示若在没有缺失的理想情况下,数字范围的右边界,最后。
之后遍历数组,将大小为l的数放到l+1位置。其中,若正好相等,则让l往下滑;若l位置的数小于等于l,则说明是垃圾值;若大于r,说明不符合理想情况,也是垃圾值;若nums[l]-1位置上的数等于l位置上的数,说明遇到重复的数且重复的数已经在该在的位置,也是垃圾值。对于垃圾值,只需要将其扔到r-1位置即可。若都不成立,说明该数符合理想情况,就把他发送到该在的位置。
总结
可以看出,因为指针不会回退,所以双指针确实可以极大程度上优化代码,基本上时间复杂度都非常良好,就是这个题目的单调性很不好想。
END
相关文章:
数据结构与算法:双指针
前言 双指针其实和滑动窗口差不多,但能使用的场景比滑动窗口更广功能更强。滑动窗口的内容在我上一篇文章数据结构与算法:滑动窗口。 一、原理 双指针的关键还是分析题目单调性,从而保证指针可以单方向滑动。 二、题目 1.按奇偶排序数组…...
Leetcode 57: 插入区间
Leetcode 57: 插入区间 问题描述: 给定一个非重叠的区间集合 intervals(按开始时间升序排列)和一个新的区间 newInterval,将新的区间插入到区间集合中并合并重叠的部分,最后返回结果区间集合。 适合面试的解法&#x…...
NLP如何训练AI模型以理解知识
一、自然语言处理(NLP)的定义与核心目标 1. 什么是自然语言处理? NLP是计算机科学与人工智能的交叉领域,旨在让机器具备以下能力: • 理解:解析人类语言(文本或语音)的语法、语义和…...
android13为账号密码做文件存储功能
注册获取外存权限 <uses-permission android:name"android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE" />申请文件存入外存权限 // Activity中 // 1. 申请PackageManag…...
Excel的行高、列宽单位不统一?还是LaTeX靠谱
想要生成田字格、米字格、带拼音标准,方便小学生书法和练字。Word,Excel之类所见即所得是最容易相当的方式。但它们处理带田字格之类背景时,如果没有专用模板、奇奇怪怪的插件,使用起来会碰到各种问题。比如,Word里面用…...
【JavaSE-5】程序逻辑控制相关练习题
1、判断一个数字是否是素数(质数) //方法1: import java.util.Scanner; public static void main(String[] args) {//判断一个数字是否是素数:除了1和它本身外没有其他数可以整除Scanner scan new Scanner(System.in);int num scan.nextInt();boolean flag tru…...
MyBatis-Plus 条件构造器的使用(左匹配查询)
在上一篇文章中,我们已经介绍了 MyBatis-Plus 条件构造器,包括 QueryWrapper 和 UpdateWrapper 的基本使用方法、常见查询条件(如等于、不等于、大于、小于)以及如何使用 Lambda 表达式来构建动态查询和更新条件。 在本文中&…...
深入理解设计模式中的单例模式(Singleton Pattern)
各类资料学习下载合集 https://pan.quark.cn/s/8c91ccb5a474 单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供全局访问点。这种模式在许多应用场景中都很有用,特别是当我们希望控制对共享资源的访问时,比…...
CES Asia 2025增设未来办公教育板块,科技变革再掀高潮
作为亚洲消费电子领域一年一度的行业盛会,CES Asia 2025(第七届亚洲消费电子技术贸易展)即将盛大启幕。今年展会规模再度升级,预计将吸引超过500家全球展商参展,专业观众人数有望突破10万。除了聚焦人工智能、物联网、…...
汽车零部件厂如何选择最适合的安灯系统解决方案
在现代制造业中,安灯系统作为一种重要的生产管理工具,能够有效提升生产线的异常处理效率,确保生产过程的顺畅进行。对于汽车零部件厂来说,选择一套适合自身生产需求的安灯系统解决方案尤为重要。 一、安灯系统的核心功能 安灯系统…...
sqlite3 c++ client选择; c++环境搭建 : abseil-cpp | fnc12/sqlite_orm
sqlite3 c client选择 今日20250305 2.4K星: 7月前最后提交核心: SRombauts/SQLiteCpp.git : 薄封装、命令式sql、非orm、支持事务2.4K星: 1月前最后提交核心: fnc12/sqlite_orm.git : 厚封装、非侵入、真orm、真泛型、类型复杂、支持事务 因真泛型导致DbInstance必须放在x.h…...
Pytorch中的主要函数
目录 一、torch.manual_seed(seed)二、torch.cuda.manual_seed(seed)三、torch.rand(*size, outNone, dtypeNone, layouttorch.strided, deviceNone, requires_gradFalse)四、给大家写一个常用的自动选择电脑cuda 或者cpu 的小技巧五、torch.version.cuda;torch.bac…...
景联文科技:以专业标注赋能AI未来,驱动智能时代的精准跃迁
在人工智能技术重塑全球产业格局的今天,高质量训练数据已成为驱动算法进化的核心燃料。作为数据智能服务领域的领军者,景联文科技深耕数据标注行业多年,以全栈式数据解决方案为核心,构建起覆盖数据采集、清洗、标注、质检及算法调…...
车载测试:智能座舱测试中多屏联动与语音交互的挑战
智能座舱作为汽车智能化发展的核心,集成了多屏联动和语音交互功能,为驾驶员和乘客提供更便捷的体验。然而,这些功能的测试面临诸多挑战,包括多屏同步性、噪声干扰和复杂场景的处理。本文将详细分析这些挑战,探讨测试方…...
深入探索WebGL:解锁网页3D图形的无限可能
深入探索WebGL:解锁网页3D图形的无限可能 引言 。WebGL,作为这一变革中的重要技术,正以其强大的功能和广泛的应用前景,吸引着越来越多的开发者和设计师的关注。本文将深入剖析WebGL的核心原理、关键技术、实践应用,并…...
仿mudou库one thread oneloop式并发服务器
项目gitee:仿muduo: 仿muduo 一:项目目的 1.1项目简介 通过咱们实现的⾼并发服务器组件,可以简洁快速的完成⼀个⾼性能的服务器搭建。 并且,通过组件内提供的不同应⽤层协议⽀持,也可以快速完成⼀个⾼性能应⽤服务器…...
Linux 文件和目录权限管理详解
文章目录 Linux 文件和目录权限管理详解介绍权限管理的核心内容权限管理访问权限查看权限更改权限所有者和用户组的设置权限设置注意事项 总结 Linux 文件和目录权限管理详解 介绍 在 Linux 系统中,文件和目录的权限管理是确保系统安全的重要组成部分。每个文件和…...
CentOS 7 aarch64上制作kernel rpm二进制包 —— 筑梦之路
环境说明 centos 7 aarch64 gcc 8.3.1 kernel 5.4.290 准备编译制作 # 安装必要的工具和包yum install rpm-devel rpmdevtools yum groupinstall "Development Tools"yum install ncurses-devel bc elfutils-libelf-devel openssl-devel # 安装gcc 8.3.1# 修改…...
Windows 图形显示驱动开发-WDDM 3.2-本机 GPU 围栏对象(二)
GPU 和 CPU 之间的同步 CPU 必须执行 MonitoredValue 的更新,并读取 CurrentValue,以确保不会丢失正在进行的信号中断通知。 当向系统中添加新的 CPU 等待程序时,或者如果现有的 CPU 等待程序失效时,OS 必须修改受监视的值。OS …...
vscode 都有哪些大模型编程插件
VSCode 中有许多基于大模型的编程插件,这些插件通过集成人工智能技术,显著提升了开发者的编程效率和体验。以下是一些主要的大模型编程插件及其功能: GitHub Copilot GitHub Copilot 是由 OpenAI 开发的插件,能够根据代码上下文自…...
常用的分布式 ID 设计方案
文章目录 1.UUID2.数据库自增 ID3.雪花算法4.Redis 生成 ID5.美团 Leaf 1.UUID 原理:UUID 是由数字和字母组成的 128 位标识符,通过特定算法随机生成,包括时间戳、计算机网卡地址等信息。常见的版本有版本 1(基于时间戳和 MAC 地…...
DAIR-V2X-R数据集服务器下载
【官方github链接】https://github.com/ylwhxht/V2X-R 点击并登录 选择并点击下载 浏览器弹窗,右键选择复制下载链接 ------------------------------------服务器下载----------------------------------------- 登录服务器,选在要下载的文件夹复制路…...
EasyRTC嵌入式视频通话SDK的跨平台适配,构建web浏览器、Linux、ARM、安卓等终端的低延迟音视频通信
1、技术背景 WebRTC是一项开源项目,旨在通过简单的API为浏览器和移动应用程序提供实时通信(RTC)功能。它允许在无需安装插件或软件的情况下,实现点对点的音频、视频和数据传输。 WebRTC由三个核心组件构成: GetUserM…...
影院购票系统(二)——uni-app移动应用开发
这一篇讲解系统的逻辑代码部分,下面是ai的讲解,也可以直接跳到代码部分进行浏览。 一、整体功能概述 这个Vue组件构建了一个完整的影院座位选择系统,涵盖从座位数据初始化、视图渲染到交互处理以及业务逻辑的整个流程。它遵循响应式编程模式…...
DeepSeek×博云AIOS:突破算力桎梏,开启AI普惠新纪元
背景 在全球人工智能技术高速迭代的背景下,算力成本高企、异构资源适配复杂、模型部署效率低下等问题,始终是制约企业AI规模化应用的关键。 DeepSeek以创新技术直击产业痛点,而博云先进算力管理平台AIOS的全面适配,则为这一技术…...
DeepSeek能画流程图吗?分享一种我正在使用的DeepSeek画流程图教程
…...
网络安全试题填空题
🍅 点击文末小卡片 ,免费获取网络安全全套资料,资料在手,涨薪更快 2018年期末题 1. 分布式防火墙系统组成不包括(D) A.网络防火墙 B.主机防火墙 C.中心管理防火墙 D.传统防火墙 2.下列不是入侵者主要行为模…...
MySQL中查看表结构
1. 使用 DESCRIBE 或 DESC 命令 DESCRIBE(或其简写 DESC)是最简单和最直接的方法,可以显示表的列信息。 语法: DESCRIBE table_name; -- 或者 DESC table_name;示例: 假设有一个名为 employees 的表,可以…...
个推助力小米米家全场景智能生活体验再升级
当AI如同水电煤一般融入日常,万物互联的图景正从想象照进现实。作为智能家居领域的领跑者,小米米家凭借开放的生态战略,已连接了超8.6亿台设备,构建起全球领先的消费级AIoT平台。如今,小米米家携手个推,通过…...
linux服务器根据内核架构下载各种软件依赖插件(例子:Anolis服务器ARM64架构内核Nginx依赖插件下载)
Anolis服务器ARM64架构内核Nginx依赖插件下载 Nginxy依赖包:阿里云镜像站搜索自己的系统如下点击系统,进入详情页面点击下载地址点击对应版本号选择Os继续点击OS点击Packagesctrf搜索资源,依次下载资源,版本建议选最新把下载好的资…...
