优选算法——双指针
前言
本篇博客为大家介绍双指针问题,它属于优选算法中的一种,也是一种很经典的算法;算法部分的学习对我们来说至关重要,它可以让我们积累解题思路,同时也可以大大提升我们的编程能力,本文主要是通过一些题目来为大家介绍,这里统一说明一下,每一道题我会粘贴原题链接,大家可以先做再来看解析,这样会更有针对性,下面进入正文。
1. 移动零
题目链接:. - 力扣(LeetCode)

题目解析:本题大家读完后应该可以很轻松地理解题目的意思,我们需要将0全部移动到数组的末尾,并且保持其他元素的顺序是不能改变的。
算法原理:这类题可以划归为数组分块问题,对于这类问题,首先想到的方法就是双指针,大家注意这里提到的指针并不是我们在C语言中学过的那个指针,这里的“指针”代表数组的下标。我们需要定义两个“指针”,一个指针用于遍历数组,另一个指针用来存储非零元素的最后一个位置,这两个“指针”会将整个数组划分为3个区间。
具体大家来看下图:
区间划分完后,我们需要让两个“指针”移动的过程中保持它们本身的性质,这样我们就可以解决这个问题,那么我们该如何保持呢?

大家可以结合题目给的例子来进行理解,上面的思路就是双指针的核心思路。
代码实现:
class Solution {
public:void moveZeroes(vector<int>& nums) {int cur=0;int dest=-1;for(cur=0;cur<nums.size();cur++){if(nums[cur]){swap(nums[++dest],nums[cur]);}}}
};
这里使用C++实现代码,一个for循环就搞定了,主要就是在于指针的调整。
2. 复写零
题目链接:. - 力扣(LeetCode)

题目解析:本题要求我们来对0进行复写,其实就是遇到0了抄两遍,不是0就抄一遍,注意题目要求就地修改,不能开辟新的数组。
算法原理:首先我们需要定义两个指针,其次需要找到最后一个复写的数,最后从后向前进行复写操作,具体大家请看下图:

这里大家要注意,我们在找最后一个复写的数的时候也同样需要用到双指针算法;其中有越界的情况,我们要进行特殊处理。
代码实现:
class Solution {
public:void duplicateZeros(vector<int>& arr){//第一步:找最后一个复写的数int cur=0;int dest=-1;int n=arr.size();while(dest<n){if(arr[cur]){++dest;}else{dest+=2;}if(dest>=n-1){break;}cur++;}//第二步:处理边界if(dest==n){arr[n-1]=0;cur--;dest-=2;}//第三步:从后向前复写while(cur>=0){if(arr[cur]){arr[dest--]=arr[cur--];}else{arr[dest--]=0;arr[dest--]=0;cur--;}}}
};
这里大家看到代码,分为三部分:找最后一个复写的数、处理边界以及复写操作;还有一个小问题,有同学会想为什么必须从后往前进行复写,不能从前往后吗?
答案是不可以,大家思考一下,如果从前往后复写,那么0要写2遍,这个时候我们原始的数据就会被覆盖,这样就无法达到题目的要求。
3. 快乐数
题目链接:. - 力扣(LeetCode)

题目解析:本题要求我们判断一个数是否为快乐数,那么我们首先要明确什么是快乐数;然后我们进行判断,是快乐数返回1,否则返回0。
算法原理:这道题我们也可以使用双指针来解决,具体来说就是快慢指针,大家可以先回想一下我们在链表的学习中遇到的这么一道题,题目要求我们判断环形链表,当时我们使用了快慢指针的方法来解决,那么本题我们同样可以使用这种思想来解决。根据之前的结论,大家首先需要明确,当我们不断进行题目要求的操作时,一定会进入一个循环,这里要么是1一直循环;要么是循环其他不为1的数据,所以每次计算得到的数可以串起来看成一个“链表”,这样就和我们之前说过的环形链表殊途同归了。我们只需要定义一个慢指针,一个快指针,在循环的过程中,快指针一定会追上慢指针,我们判断相遇的时候的值是不是1,即可判断给定的数是不是快乐数。


代码实现:
class Solution
{
public:int test(int n){int sum=0;while(n){int t=n%10;sum+=t*t;n/=10;}return sum;}bool isHappy(int n) {int slow=n;int fast=test(n);while(slow!=fast){slow=test(slow);fast=test(test(fast));}return slow==1;}
};
这里补充一个小问题,就是实现题目中要求的操作,每一位的平方和相加,这个想必大家在C语言阶段就已经接触过,这里大家看代码应该很容易理解。
4. 盛水最多的容器
题目链接:. - 力扣(LeetCode)

题目解析:本题要求找到盛水最多的容器,本质就是让我们找出两个数来确定一个容器,使这个容器的“容积”最大;那么本题大部分人的第一反应就是暴力枚举,把每一个乘积都求出来,然后对比找出最大的,这是一种很容易理解的思路,但是代码的时间复杂度会非常高,效率就比较低,所以不可行。
算法原理:本题我们要使用双指针来解决问题,具体是运用左右指针,一个指针从左往右,另一个指针从右往左,两个指针向中间靠拢,哪边高度小哪边就往里动,下面说明了这样做的原理,利用了单调性来找到规律。

代码实现:
class Solution {
public:int maxArea(vector<int>& height) {int left=0;int right=height.size()-1;int ret=0;while(left<right){int v=min(height[left],height[right])*(right-left);ret=max(ret,v);if(height[left]<height[right]){left++;}else{right--;}}return ret;}
};
5. 有效三角形的个数
题目链接:. - 力扣(LeetCode)

题目解析:本题要求我们在一组数中选出可以构成三角型的数字组合,其实就是求有多少种选法,这里大家注意看例子的提示,重复选的数也是OK的,只要是不同位置的数就满足条件。
算法原理:
本题我们不能使用暴力解法来做,那样时间复杂度太高,效率很低;那么我们进行优化,使用双指针来解决问题,具体流程大家可以看下图,首先我们先将数据进行排序,再来固定最大的数,然后定义左右两个指针,根据两种不同的情况移动指针,循环操作,就可以解决本题。

代码实现:
class Solution {
public:int triangleNumber(vector<int>& nums) {//排序sort(nums.begin(),nums.end());int ret=0;int n=nums.size();for(int i=n-1;i>=2;i--)//固定最大数{int left=0;int right=i-1;while(left<right){if(nums[left]+nums[right]>nums[i]){ret+=right-left;right--;}else{left++;}}}return ret;}
};
6. 查找总价格为目标值的两个商品
题目链接:. - 力扣(LeetCode)

题目解析:本题的要求很简单,就是让我们在一组数中找到两个数,使它们的和等于目标值。
算法原理:本题其实大部分人第一时间还是会想到暴力解法,运用了两个循环,遍历所有情况,判断是否等于target,这样做很好理解,但是代码的时间复杂度会很高,会超时,所以这种暴力解法不建议。优化版的解法就是使用双指针,定义左右指针,分为三种情况来决定指针的移动,具体大家请看下图。

代码实现:
class Solution {
public:vector<int> twoSum(vector<int>& price, int target) {int n=price.size();int left=0;int right=n-1;while(left<right){if(price[left]+price[right]<target){left++;}if(price[left]+price[right]>target){right--;}if(price[left]+price[right]==target)return {price[left],price[right]};}return {-1,-1};}};
总结
本篇博客为大家介绍了双指针算法,它可以帮助我们解决很多原本复杂的问题,大家需要掌握这种思想,当我们遇到需要将数据分区间进行处理的时候,我们可以考虑双指针,这其中还包括了快慢指针的思路,最后希望本篇博客可以为大家带来帮助,感谢阅读!
相关文章:
优选算法——双指针
前言 本篇博客为大家介绍双指针问题,它属于优选算法中的一种,也是一种很经典的算法;算法部分的学习对我们来说至关重要,它可以让我们积累解题思路,同时也可以大大提升我们的编程能力,本文主要是通过一些题…...
【Rabbitmq篇】RabbitMQ⾼级特性----消息确认
目录 前言: 一.消息确认机制 • ⾃动确认 • ⼿动确认 手动确认方法又分为三种: 二. 代码实现(spring环境) 配置相关信息: 1). AcknowledgeMode.NONE 2 )AcknowledgeMode.AUTO 3&…...
开源TTS语音克隆神器GPT-SoVITS_V2版本地整合包部署与远程使用生成音频
文章目录 前言1.GPT-SoVITS V2下载2.本地运行GPT-SoVITS V23.简单使用演示4.安装内网穿透工具4.1 创建远程连接公网地址 5. 固定远程访问公网地址 前言 本文主要介绍如何在Windows系统电脑使用整合包一键部署开源TTS语音克隆神器GPT-SoVITS,并结合cpolar内网穿透工…...
【idea】更换快捷键
因为个人习惯问题需要把快捷键替换一下。我喜欢用CTRLD删除一下,用CTRLY复制一样。恰好这两个快捷键需要互换一下。 打开file——>setting——>Keymap——>Edit Actions 找到CTRLY并且把它删除 找到CTRLD 并且把它删除 鼠标右键添加CTRLY 同样操作在Delet…...
最小的子数组(leetcode 209)
给定一个正整数数组,找到大于等于s的连续的最小长度的区间。 解法一:暴力解法 两层for循环,一个区间终止位置,一个区间起始位置,找到大于等于s的最小区间长度(超时了) 解法二:双指…...
IDEA-Plugins无法下载插件(网络连接问题-HTTP Proxy Settings)
IDEA-Plugins无法下载插件(网络连接问题) 改成如下配置: 勾选 添这个url即可:https://plugins.jetbrains.com/ 重启插件中心,问题解决。...
AWTK-WIDGET-WEB-VIEW 发布
awtk-widget-web-view 是通过 webview 提供的接口,实现的 AWTK 自定义控件,使得 AWTK 可以方便的显示 web 页面。 项目网址: https://gitee.com/zlgopen/awtk-widget-web-view webview 提供了一个跨平台的 webview 接口,是一个非…...
Mysql每日一题(if函数)
两种写法if()和case if()函数 select *,if(T.xT.y>T.z and T.xT.z>T.y and T.yT.z>T.x,Yes,No) as triangle from Triangle as T; case方法 select *, case when T.xT.y>T.z and T.xT.z>T.y and T.yT.z>T.x then Yes else No end as triangle from Trian…...
Spring Cloud Alibaba [Gateway]网关。
1 简介 网关作为流量的入口,常用功能包括路由转发、权限校验、限流控制等。而springcloudgateway 作为SpringCloud 官方推出的第二代网关框架,取代了Zuul网关。 1.1 SpringCloudGateway特点: (1)基于Spring5,支持响应…...
【动手学深度学习Pytorch】2. Softmax回归代码
零实现 导入所需要的包: import torch from IPython import display from d2l import torch as d2l定义数据集参数、模型参数: batch_size 256 # 每次随机读取256张图片 train_iter, test_iter d2l.load_data_fashion_mnist(batch_size) # 将展平每个…...
技术周总结 11.11~11.17 周日(Js JVM XML)
文章目录 一、11.11 周一1.1)问题01:js中的prompt弹窗区分出来用户点击的是 确认还是取消进一步示例 1.2)问题02:在 prompt弹窗弹出时默认给弹窗中写入一些内容 二、11.12 周二2.1) 问题02: 详解JVM中的本地方法栈本地方法栈的主要…...
MATLAB 使用教程 —— 矩阵和数组
矩阵和数组MATLAB 中矩阵和数组长什么样?MATLAB 怎么用矩阵计算?创建和操作矩阵矩阵运算示例串联 访问矩阵的元素 矩阵和数组 MATLAB 是“matrix laboratory”的缩写形式。MATLAB 主要用于处理 整个的矩阵和数组,而其他编程语言大多逐个处理…...
React教程第二节之虚拟DOM与Diffing算法理解
1、什么是虚拟DOM 虚拟DOM 是javascript的一个对象,是内存中的一种数据结构,以树的形式存储UI的状态,树中的每个节点都代表着真实的DOM,用来描述我们希望在页面看到的 HTML结构; 现在的MVVM 框架,大多使用…...
C++——类和对象(part2)
前言 本篇博客继续为大家介绍类与对象的知识,承接part1的内容,本篇内容是类与对象的核心内容,稍微有些复杂,如果你对其感兴趣,请继续阅读,下面进入正文部分。 1. 类的默认成员函数 默认成员函数就是用户…...
【FFmpeg系列】:音频处理
前言 在多媒体处理领域,FFmpeg无疑是一个不可或缺的利器。它功能强大且高度灵活,能够轻松应对各种音频和视频处理任务,无论是简单的格式转换,还是复杂的音频编辑,都不在话下。然而,要想真正发挥FFmpeg的潜…...
Python绘制雪花
文章目录 系列目录写在前面技术需求完整代码代码分析1. 代码初始化部分分析2. 雪花绘制核心逻辑分析3. 窗口保持部分分析4. 美学与几何特点总结 写在后面 系列目录 序号直达链接爱心系列1Python制作一个无法拒绝的表白界面2Python满屏飘字表白代码3Python无限弹窗满屏表白代码4…...
vue3 如何调用第三方npm包内部的 pinia 状态管理库方法
抛砖引玉: 如果在开发vue3项目是, 引用了npm第三方包 ,而且这个包内使用了Pinia 状态管理库,那我们如何去调用 npm内部的 Pinia 状态管理库呢? 实际遇到的问题: 今天在制作npm包时遇到的问题,之前Vue2版本的时候状态管理库用的Vuex ,当时调用npm包内的状态管理库很简单,直接引…...
uni-app快速入门(七)--组件路由跳转和API路由跳转及参数传递
uni-app有两种页面路由跳转模式,即使用navigator组件跳转和调用API跳转,API调转不要理解为调用后台接口的API,而是指脚本函数中使用跳转函数。 一、组件路由跳转 1.1 打开新页面 打开新页面使用组件的open-type"navigate",见下面…...
Flink升级程序和版本
Flink DataStream程序通常设计为长时间运行,如几周、几个月甚至几年。与所有长时间运行的服务一样,Flink streaming应用程序也需要维护,包括修复错误、实现改进或将应用程序迁移到更高版本的Flink集群。 这里就来描述下如何更新Flink streaming应用程序,以及如何将正在运行…...
从0安装mysql server
安装 MySQL Server 首先,你需要在 Ubuntu 上安装 MySQL 服务器。运行以下命令来安装:sudo apt update sudo apt install mysql-server安装完成后,MySQL 服务会自动启动。你可以通过以下命令检查 MySQL 服务是否正在运行: sudo systemctl status mysql如果 MySQL 正在运行,…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
