优选算法——双指针1

双指针

常⻅的双指针有两种形式,⼀种是对撞指针,⼀种是左右指针。

对撞指针:⼀般⽤于顺序结构中,也称左右指针。

  1. 对撞指针从两端向中间移动。⼀个指针从最左端开始,另⼀个从最右端开始,然后逐渐往中间逼 近。
  2. 对撞指针的终⽌条件⼀般是两个指针相遇或者错开(也可能在循环内部找到结果直接跳出循 环),也就是:
  • left == right (两个指针指向同⼀个位置)
  • left > right (两个指针错开)

快慢指针:⼜称为⻳兔赛跑算法,其基本思想就是使⽤两个移动速度不同的指针在数组或链表等序列 结构上移动。

 这种⽅法对于处理环形链表或数组⾮常有⽤。

其实不单单是环形链表或者是数组,如果我们要研究的问题出现循环往复的情况时,均可考虑使⽤快 慢指针的思想。

快慢指针的实现⽅式有很多种,最常⽤的⼀种就是: 

  • 在⼀次循环中,每次让慢的指针向后移动⼀位,⽽快的指针往后移动两位,实现⼀快⼀慢。

注:双指针只是一种思想,我们不一定真的要定义指针来实现双指针,我们可以使用特定的数值来表示指针,比如说数组的下标,某元素的值

第一题——移动零

「数组分两块」是⾮常常⻅的⼀种题型,主要就是根据⼀种划分⽅式,将数组的内容分成左右两部 分。这种类型的题,⼀般就是使⽤「双指针」来解决。

题目来源. - 力扣(LeetCode) 

思路(快排的思想:数组划分区间-数组分两块)

在本题中,我们可以⽤⼀个 cur 指针来扫描整个数组,另⼀个 dest 指针⽤来记录⾮零数序列的最后一个位置。根据 cur 在扫描的过程中,遇到的不同情况,分类处理,实现数组的划分。

在 cur 遍历期间,使 [0, dest] 的元素全部都是⾮零元素, [dest + 1, cur - 1] 的 元素全是零。

那我们要怎么做呢?很简单

我们直接看例子

我们发现1——5步均符合下面这个区间的要求

 代码

void swap(int*a,int*b)
{int tmp=*a;*a=*b;*b=tmp;
}
void moveZeroes(int* nums, int numsSize) {for(int cur = 0, dest = -1; cur < numsSize; cur++)if(nums[cur]) // 处理⾮零元素swap(&nums[++dest], &nums[cur]);}

第二题——复写零

题目来源:. - 力扣(LeetCode)

我们先审题,它这个题目到底要我们干什么,我们看下面这个图就明白了

假设上面这个是传入的数组,下面这个就是完成复写零的数组

思路:

来看看另外开辟一个数组的做法 

 把异地操作模拟成就地操作

我们先看看从前往后的双指针法行不行

显然不行

我们再看看从后往前的方式 

完全可以嘿!那我们怎么找最后一个被复写的数呢?我们还是用双指针去找

 

 但是,这个算法还不健全,它在下面这个情况会发生越界访问

代码:

void duplicateZeros(int* arr, int arrSize) {// 1. 先找到最后⼀个数int cur = 0, dest = -1, n = arrSize;while (cur < n){if (arr[cur]) dest++;else dest += 2;if (dest >= n - 1)break;cur++;}// 2. 处理⼀下边界情况if (dest == n){arr[n - 1] = 0;cur--; dest -= 2;}// 3. 从后向前完成复写操作while (cur >= 0){if (arr[cur]) arr[dest--] = arr[cur--];else{arr[dest--] = 0;arr[dest--] = 0;cur--;}}
}

第三题——快乐数

题目来源:. - 力扣(LeetCode)

 思路

先审题

要么变到一,要么循环,我们直接把它抽象成第一种情况为最后是形成所有元素都是一的环,第二种情况是所有元素都不是1的环

这不就是判断链表里是不是有环的问题吗?

 有人就想了,我们怎么定义指针?

这里我们就要注意了,双指针只是一种思想,我们不一定真的要定义指针来实现双指针,我们可以使用特定的数值来表示指针,比如说数组的下标,但是在这里我们可以用数字来表示指针

我们先看slow指针

fast指针也是同理

我们就抽象成下面这个 

 

有人就想,万一它一直不成环,一直无限循环下去怎么办?

 但是,这是不可能的

我们来证明一下

我们直接取10个9,这是超过题目范围的,而且这个值产生拆分后的数一定是超过题目的 

 所以假设题目的数的范围和这个一样大,那它的取值范围是【1,810】,也就是说在这个数值范围产生的拆分后的数值一定是在【1,810】的,也就是说它最多循环810次,到811次之后一定会产生重复的值的,所以一直循环的情况不存在

根据上述的题⽬分析,我们可以知道,当重复执⾏ x 的时候,数据会陷⼊到⼀个「循环」之中。 ⽽「快慢指针」有⼀个特性,就是在⼀个圆圈中,快指针总是会追上慢指针的,也就是说他们总会 相遇在⼀个位置上。如果相遇位置的值是 1 ,那么这个数⼀定是快乐数;如果相遇位置不是 1 的话,那么就不是快乐数。

补充知识:如何求⼀个数n每个位置上的数字的平⽅和。

a. 把数 n 每⼀位的数提取出来: 循环迭代下⾯步骤:

  • int t = n % 10 提取个位;
  • n /= 10 ⼲掉个位; 直到 n 的值变为 0 ;

b. 提取每⼀位的时候,⽤⼀个变量  tmp 记录这⼀位的平⽅与之前提取位数的平⽅和

tmp = tmp + t * t

代码

int bitSum(int n) // 返回n 这个数每⼀位上的平⽅和
{ int sum = 0;while(n){int t = n % 10;sum += t * t;n /= 10;}return sum;}bool isHappy(int n)     
{int slow = n, fast = bitSum(n);while(slow != fast){slow = bitSum(slow);fast = bitSum(bitSum(fast));}return slow == 1;
}

第四题——盛最多水的容器

题目来源:盛最多水的容器 

思路 

我们可以使用暴力枚举

但是这个会超时 

我们先拿一个数组来试试,取边界为墙,我们知道啊,容器的容积是取决于容器最矮的那一端,这里也是类似的,这里容器的容量取决于最小的——4,我们就想把4变成大点的数容器的容积不就上去了吗?于是我们向内枚举,情况如下

我们发现,我们取6为墙的时候,右边的数向左枚举,没有一个容器的容积比原来的大的

 我们再看看一个例子

算法思路: 设两个指针 left , right 分别指向容器的左右两个端点,此时容器的容积:

容器的左边界为 height[left] ,右边界为 height[right] 。

为了⽅便叙述,我们假设「左边边界」⼩于「右边边界」。

如果此时我们固定⼀个边界,改变另⼀个边界,⽔的容积会有如下变化形式:

  •  容器的宽度⼀定变⼩。
  •  由于左边界较⼩,决定了⽔的⾼度。如果改变左边界,新的⽔⾯⾼度不确定,但是⼀定不会超 过右边的柱⼦⾼度,因此容器的容积可能会增⼤。
  • 如果改变右边界,⽆论右边界移动到哪⾥,新的⽔⾯的⾼度⼀定不会超过左边界,也就是不会 超过现在的⽔⾯⾼度,但是由于容器的宽度减⼩,因此容器的容积⼀定会变⼩的。

由此可⻅,左边界和其余边界的组合情况都可以舍去。所以我们可以 left++ 跳过这个边界,继 续去判断下⼀个左右边界。 当我们不断重复上述过程,每次都可以舍去⼤量不必要的枚举过程,直到 遇。期间产⽣的所有的容积⾥⾯的最⼤值,就是最终答案。 

class Solution {
public:int maxArea(vector<int>& height)
{int left = 0, right = height.size() - 1, 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;
}
};

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

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

相关文章

MySQL-InnoDB数据存储结构

1、存储结构-页 索引结构提供了高效的索引方式&#xff0c;索引信息以及数据记录都保存在数据文件或索引文件中&#xff08;本质存储在页结构中&#xff09; 1.1、磁盘与内存交互的基本单位&#xff1a;页 在InnoDB中将数据划分为若干页&#xff0c;页的默认大小为&#xff…

webpack并行构建示例:

由于js的单线程特性&#xff0c;文件和任务时 要等待一个任务执行完成后执行下一个任务&#xff0c;但在实际开发中&#xff0c;很多任务是可以并行执行的&#xff08;如同时处理多个不同js文件或同事压缩多张图片&#xff09;&#xff0c;一些loader和插件&#xff08;thread-…

【数据结构】解密链表之旅(单链表篇)

前言 哈喽大家好&#xff0c;我是野生的编程萌新&#xff0c;首先感谢大家的观看。数据结构的学习者大多有这样的想法&#xff1a;数据结构很重要&#xff0c;一定要学好&#xff0c;但数据结构比较抽象&#xff0c;有些算法理解起来很困难&#xff0c;学的很累。我想让大家知道…

自制无感无刷电机驱动板

自制无感无刷电机驱动板 分别测试了基于C251的STC32G单片机、Arduino AVR的ATmega328PB、以及ARM的ST32F103单片机。 &#x1f9f2;测试转动效果 ✒目前市面上开源的有关无刷电机的项目数不胜数&#xff0c;其控制原理都大同小异&#xff0c;在没有领透其技术要领情况下&#x…

苍穹外卖项目---------收获以及改进(9-12)

①Spring Task-------实现系统定时任务 概念&#xff1a; 应用场景&#xff1a; 使用步骤&#xff1a; 实现订单超时和前一天派送中的订单的自动任务处理&#xff1a; Component Slf4j public class Mytask {Autowiredprivate OrderServiceimpl orderServiceimpl;/*** 处理订…

yarn 安装以及报错处理

前一种报错是由于没有安装yarn导致的&#xff0c;使用以下命令即可安装&#xff1a; npm install -g yarn 如果成功安装&#xff0c;将显示Yarn的版本号。 yarn --version 第二种报错是因为系统上的执行策略限制导致的。执行策略是一种安全功能&#xff0c;用于控制在计算机…

Kafka官方文档中文版+Kafka面试题详解!

你了解kafka吗&#xff1f;目前它在一线互联网公司以迅雷不及掩耳之势得到了广泛的应用。但究竟是什么呢&#xff1f;Kafka最初于2011年在LinkedIn开发&#xff0c;自那时起经历了很多改进。如今它是一个完整的平台&#xff0c;允许您冗余地存储荒谬的数据量&#xff0c;拥有一…

SH150S1光电吊舱

SH150S1光电吊舱 1产品应用 SH150S1是一款三轴三光吊舱&#xff0c;集成了最远测程达3.0km&#xff0c;精度小于2米的半导体激光测距机&#xff0c;640512高分辨率红外相机&#xff0c;30倍光学变倍可见光相机以及高稳定精度平台框架&#xff1b;可安装于中小型无人机&#x…

【每日刷题】Day40

【每日刷题】Day40 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 202. 快乐数 - 力扣&#xff08;LeetCode&#xff09; 2. 217. 存在重复元素 - 力扣&#xff08;Le…

vue2 报错,警告 解决方法 component name“Index“should always be multi-word

报错原因&#xff1a; 组件名称应该为俩个或俩个以上单词组成的&#xff0c;并且还要是大驼峰命名&#xff0c;例如&#xff1a;MyIndex&#xff0c;MyLogin等 解决方法一&#xff1a; 将组件名称改为俩个或俩个以上单词组成的名称&#xff0c;且为大驼峰命名&#xff0c;例如…

Postman基础功能-Collection集合和批量运行

一、Collection&#xff08;集合&#xff09;介绍 当我们对一个或多个系统中的很多接口用例进行维护时&#xff0c;首先想到的就是对接口用例进行分类管理&#xff0c;同时还希望对这批接口用例做回归测试。 在 Postman 中也提供了这样一个功能&#xff0c;就是 Collec…

免费的GPT4终于要来了!OpenAI直播发布会详细解读!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

Docker下载镜像出现“missing signature key”如何解决?

“missing signature key” 通常与 Docker 配置有关&#xff0c;具体是 Docker 试图验证镜像的签名但未能找到相应的密钥。这种情况可能发生在启用了 Docker Content Trust (DCT) 的环境中&#xff0c;DCT 是一种安全功能&#xff0c;要求所有镜像必须有签名才能拉取。 原因 …

刚刚OpenAI发布ChatGPT-4o模型,免费使用GPT4o并免费提供更多功能

就在今日凌晨1点&#xff0c;OpenAI举行了春季发布会&#xff0c;发布了GPT-4o 并免费提供更多功能。 亲测GPT-4o已经可以免费试用&#xff0c;每个人都可以使用它并从中受益&#xff0c;GPT4终于不再是少部分人的玩物。 点击加入ChatGPT4交流群&#xff1a;https://www.aijour…

微信小程序发送订阅消息sendMessage

微信小程序发送订阅消息sendMessage 请注意订阅消息一次性订阅只只能授权一次接受一条消息多次授权会累加接受次数&#xff0c;wx.requestSubscribeMessage调用授权 目前长期性订阅消息仅向政务民生、医疗、交通、金融、教育等线下公共服务开放 //授权弹框&#xff0c;只弹出…

交通地理信息系统实习教程(二)

这篇文章服务于GIS背景用户以及有志于GIS的朋友 操作源数据位置&#xff1a;【免费】交通地理信息系统实习二源数据资源-CSDN文库 软件安装包位置&#xff1a;【免费】TransCad-交通地理信息系统软件资源-CSDN文库 一、最短路径分析 1.1软件启动说明 这里需要给出一个必要的…

硬件FMEA与软件FMEA的区别——FMEA软件

​免费试用FMEA软件-免费版-SunFMEA 在产品开发和制造过程中&#xff0c;失效模式与影响分析&#xff08;FMEA&#xff09;作为一种预防性的质量工具&#xff0c;对于确保产品性能和质量至关重要。然而&#xff0c;硬件FMEA和软件FMEA在应用和实践方面存在显著的区别。本文旨在…

基于阿里云向量检索 Milvus 版与 PAI 搭建高效的检索增强生成(RAG)系统

阿里云向量检索 Milvus 版现已无缝集成于阿里云 PAI 平台&#xff0c;一站式赋能用户构建高性能的检索增强生成&#xff08;RAG&#xff09;系统。您可以利用 Milvus 作为向量数据的实时存储与检索核心&#xff0c;高效结合 PAI 和 LangChain 技术栈&#xff0c;实现从理论到实…

java面试题:判断字符串包含字母、数字、空格、符号的数量

在Java中&#xff0c;你可以使用正则表达式来检查字符串中包含多少个字母、数字、空格和符号。也可以使用基础api来实现业务逻辑&#xff0c;方法如下&#xff1a; 1 使用Character类的静态方法 以下代码定义了一个countCharacters方法&#xff0c;它遍历字符串中的每个字符&a…

解决:微信支付 由于商家传入的H5交易参数有误,该笔交易暂时无法完成,请联系商家解决

微信支付参数配置完成后请求报这个。在网上搜索后发现是ip配置的问题&#xff0c;我配置的是127.0.0.1。 而微信支付的时候需要获取用户的真实ip