【java算法专场】双指针(上)

目录

前言

基本原理

对撞指针

快慢指针

移动零

算法思路

算法步骤

代码实现

算法分析

复写零

算法思路

算法步骤

代码实现

 快乐数

算法思路

算法步骤

代码实现

盛最多水的容器

​编辑算法思路

代码实现 


前言

双指针是一种在数组或链表等线性数据结构中高效解决问题的算法思想,适用于查找、排序、去重等场景。

基本原理

双指针的原理主要是利用两个指针(或索引)从不同起点出发,按照某种规则移动,直至满足某种终止条件

常见的双指针有两种形式:1、对撞指针,2、快慢指针

本篇主要讲解快慢指针。

对撞指针

一般用于顺序结构中,也称为左右指针

思路

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

                      left==right(两个指针指向同一个位置)

                      left>right(两个指针错开)

快慢指针

⼜称为⻳兔赛跑算法,其基本思想就是使⽤两个移动速度不同的指针在数组或链表等序列 结构上移动。对于处理环形链表或者数组非常有用。

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

快慢指针的实现⽅式有很多种,最常⽤的⼀种就是: 在⼀次循环中,每次让慢的指针向后移动⼀位,⽽快的指针往后移动两位,实现⼀快⼀慢。

移动零

算法思路

在本道题中,我们可以定义一个right来扫描数组,定义一个left,负责当right遇到非0数时,与left进行交换。当right遍历完数组后,也就将数组按照其相对顺序,把非0数移动到left之前,把所有0移动到left之后。

算法步骤

  1. 定义双指针left,right

  2. 让right先走

  3. 当right遇到非0数,与left进行交换,再让left++

  4. 当right遍历完数组,移动结束

 

代码实现

 /*** 交换数组中两个位置的元素。** @param nums 输入的整数数组。* @param i 第一个位置的索引。* @param j 第二个位置的索引。*/public void swap(int[] nums, int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}/*** 将数组中的所有零移动到末尾,同时保持非零元素的相对顺序不变。** @param nums 输入的整数数组。*/public void moveZeroes(int[] nums) {// 如果数组为空,则无需进行任何操作if (nums.length == 0) {return;}int left = 0;int right = 0;// 遍历数组,将非零元素依次交换到数组的左侧while (right < nums.length) {if (nums[right] != 0) {// 交换当前非零元素到左侧swap(nums, left, right);// 左指针向右移动,准备交换下一个非零元素left++;}// 右指针继续向右移动,扫描下一个元素right++;}}

算法分析

时间复杂度为O(N),只遍历了一遍数组,空间复杂度O(1),只用到了常数个变量。 

复写零

算法思路

利用双指针

  • cur指针:初始化为0,负责从数组的起始位置遍历数组,用于查找0元素并对新数组进行布局,记录新数组最后一个元素
  • dest指针:初始化为-1,当cur在遍历时,遇到0走两步,非0走1步,当dest走到数组末尾时,此时就能确定cur要复写的起始位置。当确定完cur要开始复写的位置,从后往前进行复写。

算法步骤

  1. 复写预备:首先通过cur对数组进行遍历,在dest越界的情况下,dest能到的位置为数组的最后一个元素位置,此时停止遍历。
  2. 处理dest越界情况:如果dest在数组倒数第二个元素位置,而此时cur下标的值为0,那么dest就会越界。由于数组已满,只能将数组最后一个元素复制为0,并相应调整cur和dest的位置(cur--,dest-=2)
  3. 从后往前复制:从dest出发,判断cur的值是否为0,为0,dest位置先复制为0,再dest--,再复制为0,再dest--,若cur位置的值不为0,则让cur位置的值给dest位置,dest--,当dest<0时,复制结束

代码实现

  /*** 复制数组中的零。* 将数组arr中的零复制一倍,并尽可能地填入数组中,可能会覆盖原数组的部分元素。* 如果复制零后,数组末尾无法再放置一个零,则将最后一个非零元素替换为零。* 此方法直接在原数组上进行操作,不返回新数组。** @param arr 原数组,将在此数组上进行操作。*/public void duplicateZeros(int[] arr) {// 获取数组长度int len = arr.length;// 初始化当前索引cur和目标索引destint cur = 0;int dest = -1; // dest从-1开始,因为下一个要填入的位置是dest+1// 遍历数组,计算每个非零元素和零元素应该填入的位置int dest=-1;//dest从-1开始for (; cur < len; cur++) {// 如果当前元素不为零,目标索引移动一步// 如果当前元素为零,目标索引移动两步// 判断cur是否为0,若为0,dest移动2步,反之,移动1步if (arr[cur] != 0) {dest++;} else {dest += 2;}// 如果目标索引超出或等于数组长度减一,则无法再放置更多元素,结束循环// 判断dest是否到到数组末尾,若到达末尾,则说明不需要移动,直接返回if (dest >= len - 1) {break;}}// 检查是否需要将最后一个元素替换为零if (dest == len) {arr[len - 1] = 0;cur--;dest -= 2;}// 从后向前复制元素,实现零的复制// 进行复写while (dest >= 0) {// 如果当前元素为零,则在目标位置复制两个零if (arr[cur] == 0) {arr[dest--] = 0;arr[dest--] = 0;} else {// 如果当前元素不为零,则复制到目标位置arr[dest--] = arr[cur];}cur--;}}

时间复杂度为O(N),空间复杂度为O(1).

 快乐数

算法思路

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

算法步骤

  • isSum:主要用来求⼀个数 n 每个位置上的数字的平⽅和。
  • isHappy:用来判断一个数是不是快乐数
  1. 在isHappy中,首先定义两个指针:快指针fast和慢指针slow,slow初始化为n,fast初始化为isSum(n),即先进行一次计算。
  2. 循环判断:条件为(slow!=fast),在while循环中,slow每次调用一次isSum进行计算,而fast则每次调用两次isSum进行计算。当slow和fast的值相等时,则说明成环。
  3. 返回:当循环结束后,返回slow==1,即判断n是不是快乐数。

代码实现

/*** 计算一个数字的各位平方和。* * @param n 输入的整数* @return 各位数字的平方和*/public int isSum(int n){int sum=0;while(n!=0){sum+=Math.pow(n%10,2);n=n/10;}return sum;}/*** 判断一个数字是否为“快乐数”。* “快乐数”是指在一系列操作后,最终得到1的数。* 操作是将数字的各位数的平方相加,然后重复这个过程。* * @param n 输入的整数,用于判断是否为快乐数* @return 如果n是快乐数,返回true;否则返回false*/public boolean isHappy(int n) {int slow=n;int fast=isSum(n);while(slow!=fast){slow=isSum(slow);fast=isSum(isSum(fast));//快指针走两步,慢指针走一步}return slow==1;}

代码时间复杂度为O(logN),空间复杂度为O(1).

盛最多水的容器

算法思路

  1. 设两个指针 left , right 分别指向容器的左右两个端点,此时容器的容积 : v = (right - left) * min( height[right], height[left]) 容器的左边界为 height[left] ,右边界为 height[right] 。
  2. 为了⽅便叙述,我们假设「左边边界」⼩于「右边边界」。
  3. 如果此时我们固定⼀个边界,改变另⼀个边界,⽔的容积会有如下变化形式:
  4.  容器的宽度⼀定变⼩。
  5.  由于左边界较⼩,决定了⽔的⾼度。如果改变左边界,新的⽔⾯⾼度不确定,但是⼀定不会超右边的柱⼦⾼度,因此容器的容积可能会增⼤。
  6.  如果改变右边界,⽆论右边界移动到哪⾥,新的⽔⾯的⾼度⼀定不会超过左边界,也就是不会过 现在的⽔⾯⾼度,但是由于容器的宽度减⼩,因此容器的容积⼀定会变⼩的。

由此可⻅,左边界和其余边界的组合情况都可以舍去。所以我们可以 left++ 跳过这个边界,继续去判断下⼀个左右边界。

当我们不断重复上述过程,每次都可以舍去⼤量不必要的枚举过程,直到 left 与 right 相遇。期间产⽣的所有的容积⾥⾯的最⼤值,就是最终答案.

代码实现

  /*** 计算两个非递减序列中形成的最大矩形区域的面积。* 该方法使用双指针技术来找到最大的矩形面积,避免了对每个可能的矩形进行遍历,提高了效率。* * @param height 一个整数数组,表示每个位置的高度。* @return 返回最大的矩形面积。*/public int maxArea(int[] height) {// 初始化左指针、面积为0,和右指针int left = 0;int V = 0;int right = height.length - 1;// 当左指针小于右指针时,进行循环while (left < right) {// 计算当前形成的矩形的最小高度int h = Math.min(height[left], height[right]);// 计算当前形成的矩形的宽度int len = right - left;// 更新当前的最大面积V = Math.max(V, h * len);// 根据左指针和右指针指向的高度,移动指针if (height[left] < height[right]) {left++;} else {right--;}}// 返回最大面积return V;}

该算法的时间复杂度为O(N)只遍历了一遍数组,空间复杂度为O(1),只使用了常数个变量.

双指针上篇就先到这~

若有不足,欢迎指正~

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

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

相关文章

CV每日论文--2024.6.26

1、StableNormal: Reducing Diffusion Variance for Stable and Sharp Normal 中文标题&#xff1a;StableNormal&#xff1a;减少扩散方差以实现稳定且锐利的法线 简介&#xff1a;本文介绍了一种创新解决方案&#xff0c;旨在优化单目彩色输入&#xff08;包括静态图片与动态…

CCS的安装步骤

CCS的安装步骤 安装之前有几件重要的事情要做&#xff1a; 首先肯定是要下载安装包啦&#xff01;点击此处是跳到官网下载地址安装包不能处的路径中不能包含中文关闭病毒防护和防火墙&#xff0c;以及其他杀毒软件最后是在重启后进行安装 主要的步骤如下&#xff1a; 找到安…

PDF转成清晰长图

打开一个宝藏网址在线PDF转换器/处理工具 - 在线工具系列 点击图下所示位置 按照图下所示先上传文件&#xff0c;设置转换参数后点击转换&#xff0c;等待 等待转换完成后&#xff0c;可以在转换结果处选择下载地址&#xff0c;点击即可进行下载使用了。对比了其他几个网站的转…

.NET C# Asp.Net Core Web API 配置 Nginx

.NET C# Asp.Net Core Web API 配置 Nginx 目录 .NET C# Asp.Net Core Web API 配置 Nginx1 创建Asp.Net Core Web API应用2 接口代码3 发布4 启动服务5 Nginx安装6 配置Nginx7 启动Nginx8 测试9 Nginx日志10 附&#xff1a; 1 创建Asp.Net Core Web API应用 2 接口代码 Weath…

高考志愿填报选专业,解读“冲稳保”三步策略

高考界流传着一句话“一分压倒千人”&#xff0c;在特定的分数段&#xff0c;比别人高一分&#xff0c;高考排名就比别人高一千并不是危言耸听&#xff0c;而利用好这些分数和排名&#xff0c;则有利于我们人生进入新的阶段。 纵观每年的高考&#xff0c;无论是老师考生还是家…

“北京到底有谁在啊”影视APP开发,解锁最简单的快乐

随着电视剧《玫瑰的故事》在腾讯视频APP热播&#xff0c;APP也增加了很多热度&#xff0c;一款丰富的影视APP&#xff0c;无论是热门大片、经典影视剧、还是最新综艺节目&#xff0c;能畅享无限精彩的影视内容&#xff01; 开发影视APP&#xff0c;需要专业的技术服务商来解决…

[leetcode]k-th-smallest-in-lexicographical-order 字典序的第K小数字

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int getSteps(int curr, long n) {int steps 0;long first curr;long last curr;while (first < n) {steps min(last, n) - first 1;first first * 10;last last * 10 9;}return steps;}int find…

kettle使用手册 安装9.0版本 建议设置为英语

0.新建转换的常用组件 0. Generate rows 定一个字符串 name value就是字符串的值 0.1 String operations 字段转大写 去空格 1. Json input 来源于一个json文件 1.json 或mq接收到的data内容是json字符串 2. Json output 定义Jsonbloc值为 data, 左侧Fieldname是数据库查…

vue3-登录小案例(借助ElementPlus+axios)

1.创建一个vue3的项目。 npm create vuelatest 2.引入Elementplus组件库 链接&#xff1a;安装 | Element Plus npm install element-plus --save 在main.js中引入 import ElementPlus from "element-plus";import "element-plus/dist/index.css";ap…

SAP ABAP 常用实用类

文章目录 前言一、输出 展示 数据信息 a.将 JSON 格式化为可读 并以弹框形式输出 b.将内表内容以表格形式输出 c.弹框形式显示 HTML 内容。也能显示包含js 的html。也可以显示pdf 图片 二、输入 获取 数据信息 a.弹框 添加 输入框…

算法基础详解

大O记法 为了统一描述&#xff0c;大O不关注算法所用的时间&#xff0c;只关注其所用的步数。 比如数组不论多大&#xff0c;读取都只需1步。用大O记法来表示&#xff0c;就是&#xff1a;O(1)很多人将其读作“大O1”&#xff0c;也有些人读成“1数量级”。一般读成“O1”。虽…

DM达梦数据库转换、条件函数整理

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

系统运维面试题总结(网络基础类)

系统运维面试题总结&#xff08;网络基础类&#xff09; 网络基础类第七层&#xff1a;应用层第六层&#xff1a;表示层第五层&#xff1a;会话层第四层&#xff1a;传输层第三层&#xff1a;网络层第二层&#xff1a;数据链路层第一层&#xff1a;物理层 类似面试题1、TCP/IP四…

802.11漫游流程简单解析与笔记_Part2_02_wpa_supplicant、cfg80211、nl80211内核与驱动的关系

wpa、cfg80211、nl80211内核与驱动的关系示意图如下&#xff1a; nl80211和cfg80211都是内核定义的标准接口&#xff0c;目的是规范驱动和应用的统一调用&#xff0c;wpa中常出现nl80211就是通过内核的nl80211接口调用对应cfg80211的部分&#xff0c;进而控制驱动收发数据或切换…

windows 安装 Kubernetes(k8s)

windows 安装 docker 详情见&#xff1a; https://blog.csdn.net/sinat_32502451/article/details/133026301 minikube Minikube 是一种轻量级的Kubernetes 实现&#xff0c;可在本地计算机上创建VM 并部署仅包含一个节点的简单集群。 下载地址&#xff1a;https://github.…

安宝特方案 | AR术者培养:AR眼镜如何帮助医生从“看”到“做”?

每一种新药品的上市都需要通过大量的临床试验&#xff0c;而每一种新的手术工具在普及使用之前也需要经过反复的实践和验证。医疗器械公司都面临着这样的挑战&#xff1a;如何促使保守谨慎的医生从仅仅观察新工具在手术中的应用&#xff0c;转变为在实际手术中实操这项工具。安…

mysql岗位实习----教务系统管理

教务管理系统 一、DDL CREATE TABLE users (user_id int(11) NOT NULL AUTO_INCREMENT COMMENT 用户ID,username varchar(50) NOT NULL COMMENT 用户名,password varchar(255) NOT NULL COMMENT 密码,gender enum(男,女) NOT NULL COMMENT 性别,email varchar(100) DEFAULT N…

【0-1系列】从0-1快速了解搜索引擎Scope以及如何快速安装使用(下)

前言 近日&#xff0c;社区版家族正式发布V2024.5版本&#xff0c;其中&#xff0c;社区开发版系列重磅发布Scope开发版以及StellarDB开发版。 为了可以让大家更进一步了解产品&#xff0c;本系列文章从背景概念开始介绍&#xff0c;深入浅出的为读者介绍Scope的优势以及能力…

Renesas MCU使用SCI_I2C驱动HS3003

目录 概述 1 软硬件介绍 1.1 软件版本信息 1.2 认识HS3003 1.2.1 HS3003特性 1.2.2 HS3003寄存器 1.2.2.1 温湿度数据寄存器 1.2.2.2 参数寄存器 1.2.2.3 一个参数配置Demo 1.2.3 温湿度值转换 1.2.4 HS3003应用电路 1.2.4.1 PIN引脚定义 1.2.4.2 sensor 应用电路 …

怎样恢复数据?原来只要3个方法,真是救大命了

无论是工作文件&#xff0c;还是个人的照片、视频&#xff0c;手机数据都承载着我们的记忆和努力。但如果不小心删除了&#xff0c;我们该怎样恢复数据呢&#xff1f;其实&#xff0c;恢复数据并不是一件复杂的事情&#xff0c;只要掌握正确的方法&#xff0c;我们就能有效地找…