【算法】【优选算法】双指针(上)

目录

  • 一、双指针简介
    • 1.1 对撞指针(左右指针)
    • 1.2 快慢指针
  • 二、283.移动零
  • 三、1089.复写零
    • 3.1 双指针解题
    • 3.2 暴力解法
  • 四、202.快乐数
    • 4.1 快慢指针
    • 4.2 暴力解法
  • 五、11.盛最多⽔的容器
    • 5.1 左右指针
    • 5.2 暴力解法

一、双指针简介

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

1.1 对撞指针(左右指针)

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

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

1.2 快慢指针

快慢指针:⼜称为⻳兔赛跑算法,其基本思想就是使⽤两个移动速度不同的指针在数组或链表等序列结构上移动。
这种⽅法对于处理环形链表或数组⾮常有⽤。其实不单单是环形链表或者是数组,如果我们要研究的问题出现循环往复的情况时,均可考虑使⽤快慢指针的思想。
快慢指针的实现⽅式有很多种,最常⽤的⼀种就是:

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

二、283.移动零

题目链接:283.移动零
题目描述:

题目解析:
这道题目要求十分清晰,把0全部放到非0元素后,且非0元素顺序不变。

解题思路:
我们使用两个指针:

  • 指针dest指向,已经被处理过全是非0的数的最后一个坐标;
  • 指针cur指向,非0元素。
  • 使用这两个指针我们将数组分成了3片区域[0, dest]全是非0,[dest+1,cur-1]全是0,[cur,nums.length-1]未处理区。
  • 所以我们只需要将cur位置的元素与dest+1位置元素交换即可。
  • 由与存在第一个数就是nums[0] = 0的可能,所以dest初始值为-1。
  • 然后再后续cur遍历数组过程中cur遇到非0就交换,dest到dest+1位置。

解题代码:

//时间复杂度O(n)
//空间复杂度O(1)
import java.util.*;
class Solution {public void moveZeroes(int[] nums) {int dest = -1;for(int cur = 0;cur < nums.length; cur++) {if(nums[cur] != 0) {int temp = nums[++dest];nums[dest] = nums[cur];nums[cur] = temp;}}}
}

三、1089.复写零

题目链接:1089.复写零
题目描述:

题目解析:数组长度固定,当从前往后遇到0就在该0和后面元素中插入一个0。

3.1 双指针解题

思路来源:

  • 异地(即拿两个数组)操作时:我们遇到非0就填入另一个数组,遇到0时就填两个0。
  • 那么我们就地(该数组上操作)操作时,我们直接模拟上面的操作,
  • 先考虑两指针从前往后时,当遇到0就将下一个位置也置为0,但是这样我们就拿不到下一个位置的值,也不要说记录下来就行,你也不知道几个0连在一起,需要记录几次。
  • 再考虑从后往前看。

解题思路:

  • 指针dest指向,最后结果的最后一个数,例如示例一就指向下标为6的nums[6] = 4。
  • 指针cur指向,数组尾即arr.length-1。
  • 我们将dest向前走,遇到0时cur下标和cur前一个元素都置为0,即arr[cur–] = 0执行两次
  • 遇到非0就直接将cur下标元素置为arr[dest]即可。
  • 特殊情况,如果我们最后需要写的是0,只就需要单独执行一次arr[cur–] = 0,就像下面这种情况,如果不单独处理,我们的cur就需要减4次,就会造成数组越界。
  • 在查找dest初始位置的时候,我们只需要让dest先遍历一遍数组,记录遇到0的个数,当0个数与dest下标和等于数组长度-1的时候,此时的dest就是初始位置。

解题代码:

//时间复杂度O(n)
//空间复杂度O(1)
import java.util.*;
class Solution {public void duplicateZeros(int[] arr) {int zeroNum = 0;//需要复写0个数int dest = 0;for(; dest < arr.length; dest++) {if(arr[dest] == 0) zeroNum++;if(dest + zeroNum >= arr.length - 1) break;}int cur = arr.length - 1;//特殊情况if(dest + zeroNum > arr.length - 1) {arr[cur--] = arr[dest--];}while(dest >= 0) {if(arr[dest] != 0) {arr[cur--] = arr[dest--];}else {arr[cur--] = 0;arr[cur--] = 0;dest--;}}}
}

3.2 暴力解法

解题思路:

  • 我们从前向后遍历数组,当遇到arr[i+1] == 0的时候就将后续元素整体向后移动腾出 i+1 下标存放0。
  • 整体向后移动思路,用一个变量将前一个数组元素记录下来,与当前元素交换,且该变量更新为当前元素值。

解题代码:

//时间复杂度O(n^2)
//空间复杂度O(1)
import java.util.*;
class Solution {public void duplicateZeros(int[] arr) {int len = arr.length;for(int i = 0; i < len - 1; i++) {if(arr[i] == 0) {int prev = arr[i+1];                 for(int j = i + 2; j < len; j++) {int tmp = arr[j];arr[j] = temp;prev = tmp;}arr[++i] = 0;}}}
}

四、202.快乐数

题目链接:202.快乐数
题目描述:

4.1 快慢指针

题目解析:

  • 快乐数的定义题目已经给的非常详细了,但是我们最值得注意的是无限循环,这句话的意思就是无论是不是快乐数,都会循环。
  • 其实这个无限循环的原理是因为 int最大值2^31 - 1 = 2147483647,就算是9999999999这样10个9的各位数平方和为810,所以在这个int范围中的各位数平方和一定会落到 [0,810]之间,所以最多循环811次就会出现重复的数了。
  • 这就可以使用快慢指针,当指针值相同的时候,我们只需要判断这个值是否为1即可。

解题代码:

//时间复杂度O(n)
//空间复杂度O(1)
import java.util.*;
class Solution {public boolean isHappy(int n) {int slow = sum(n);int fast = sum(sum(n));while(slow != fast) {slow = sum(slow);fast = sum(sum(fast));}       return slow == 1;}//求各位数平方和private int sum(int n) {int sum = 0;while(n > 0) {sum +=(n % 10) * (n % 10);n /= 10;}return sum;}
}

4.2 暴力解法

解题思路:
我们只需要使用一个栈来将每次的平方和记录下来,判断是否其中已经有该值,此时值为1就是快乐数,不为1就不是快乐数。

题目代码:

//时间复杂度O(n)
//空间复杂度O(n)
import java.util.*;
class Solution {public boolean isHappy(int n) {int[] arr = new int[820];int i = 0;arr[i++] = n;while(true) {int temp = 0;while(n > 0) {temp += (n % 10) * (n % 10);n /= 10;}n = temp;if(contains(arr,n,i)) break;else arr[i++] = n;}return n == 1;}//判断是否包含private boolean contains(int[] arr, int n, int len) {for(int i = 0; i < len; i++) {if(arr[i] == n) return true;}return false;}
}

五、11.盛最多⽔的容器

解题代码:11.盛最多⽔的容器
题目描述:

题目分析:

  • 这道题就是算容积(即两边下标差值 和 两边最短的乘积)最大。

5.1 左右指针

解题思路:

  • 我们可以分析,当我们最开始时区底边最大也就是左指针为0,右指针为height.length-1。
  • 如果我们移动指针,底边大小一定减小。
  • 而高是有两边最小值决定,当我们移动较大值的指针时,后续的高一定是小于等于此时的高,这样高也减小,容积就是一直减小的。
  • 而我们移动较小值的指针时,后续的高是有可能超过此时的高的,容积就有机会变大。
  • 所以我们每次移动较小值的指针。
  • 容积计算(right - left) * Math.min(height[left], height[right])。

解题代码:

//时间复杂度O(n)
//空间复杂度O(1)
import java.util.*;
class Solution {public int maxArea(int[] height) {int ret = 0;int left = 0;int right = height.length - 1;while(left < right) {ret = Math.max(ret, (right - left) * Math.min(height[left], height[right]));if(height[left] < height[right]) left++;else right--;}return ret;}
}

5.2 暴力解法

解题思路:
反正是求容积的最大值,我们直接使用两层for循环将每个容积可能列举出来求最大值即可。
但是会超时。

解题代码:

//时间复杂度O(n^2)
//空间复杂度O(1)
import java.util.*;
class Solution {public int maxArea(int[] height) {int ret = 0;for(int i = 0; i < height.length - 1; i++) {for(int j = i + 1; j < height.length; j++) {ret = Math.max(ret, (j - i) * Math.min(height[j], height[i]));}}return ret;}
}

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

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

相关文章

集成学习(2)

AdaBoost 基本概念 AdaBoost&#xff08;Adaptive Boosting&#xff0c;自适应增强&#xff09;&#xff0c;其自适应在于&#xff1a;前一个基本分类器分错的样本会得到加强&#xff0c;加权后的全体样本再次被用来训练下一个基本分类器。同时&#xff0c;在每一轮中加入一个…

多线程案例---单例模式

单例模式 什么是设计模式呢&#xff1f; 设计模式就好比棋手中的棋谱。在日常开发中&#xff0c;会会遇到很多常见的“问题场景”&#xff0c;针对这些问题场景&#xff0c;大佬们就设计了一些固定套路&#xff0c;按照这些固定套路来实现代码或应对这些问题场景&#xff0c;也…

第十九章 Vue组件之data函数

目录 一、引言 二、示例代码 2.1. 工程结构图 2.2. main.js 2.3. App.vue 2.4. BaseCount.vue 三、运行效果 一、引言 在Vue CLI脚手架中一个组件的data选项必须是一个函数&#xff0c;以此保证每个组件实例&#xff0c;维护独立的一份数据对象。每次创建新的组件实…

mabtisx突然不起作用:mapper跳转不到xml

解决&#xff1a;进入官方下载&#xff1a;JetBrains Marketplace 选择和你idea对应的版本号 切内网下载

ComfyUI正式版来袭!一键安装无需手动部署!支持所有电脑系统

ComfyUI V1重磅发布&#xff1a;迈向AI图像处理新时代 近日&#xff0c;ComfyUI团队正式推出了备受期待的ComfyUI V1版本&#xff0c;为图像生成和处理的AI用户带来了全新的生态体验。这一版本不仅彻底解决了以往版本中繁琐的安装和兼容问题&#xff0c;还大幅提升了易用性&…

pycharm设定代码模板

1、在文件点击设置 ​​​​​​​ ​​​​​​​ 2、点击编辑器--实时模板--找到需要插入模板的位置如我要插入HTML的模板---选择--点击实时模板 3、如图&#xff1a; 4、添加模板内容&#xff0c;如果模板有变量可以在编辑变量处点击编辑 5、编辑变量 6、点…

蘑菇书(EasyRL)学习笔记(2)

1、序列决策 1.1、智能体和环境 如下图所示&#xff0c;序列决策过程是智能体与环境之间的交互&#xff0c;智能体通过动作影响环境&#xff0c;环境则返回观测和奖励。智能体的目标是从这些反馈中学习出能最大化长期奖励的策略&#xff0c;这一过程通过不断试错和调整实现强化…

SQL进阶技巧:如何利用三次指数平滑模型预测商品零售额?

目录 0 问题背景 1 数据准备 2 问题解决 2.1 模型构建 &#xff08;1&#xff09;符号规定 &#xff08;2&#xff09;基本假设 &#xff08;3&#xff09;模型的分析与建立 2.2 模型求解 3 小结 0 问题背景 1960年—1985年全国社会商品零售额如图1 所示 表1全国社…

Rsync远程同步详细介绍

一、rsync介绍 rsync是一款开源的、快速的、多功能的、可实现全量及增量的本地或远程数据同步备份的优秀工具。并且可以不进行改变原有数据的属性信息&#xff0c;实现数据的备份迁移特性。 rsync软件支持跨平台&#xff0c;适用于unix/ linux/windows等多种操作系统平台。rsyn…

无人机之自动控制原理篇

一、飞控系统 无人机飞控是指无人机的飞行控制系统&#xff0c;是无人机的大脑。飞控系统通过传感器、控制器和执行机构三部分实现对无人机的自动控制。 传感器&#xff1a;传感器负责收集无人机的姿态、速度、高度等信息。常见的传感器包括陀螺仪、加速度计、磁力计、气压计、…

得物App获评新奖项,正品保障夯实供应链创新水平

近日&#xff0c;得物App再度获评新奖项——“2024上海市供应链创新与应用优秀案例”。 本次奖项为上海市供应链领域最高奖项&#xff0c;旨在评选出在供应链创新成效上处于领先地位、拥有成功模式和经验的企业。今年以来&#xff0c;得物App已接连获得“上海市质量金奖”、“科…

STM32F103C8T6学习笔记3--按键控制LED灯

1、实验内容 S4、S5分别接PB12和PB13&#xff0c;实验要求&#xff0c;按下S4&#xff0c;D1亮&#xff0c;D2灭&#xff1b;按下S5&#xff0c;D2亮&#xff0c;D1灭。 由于按键学习的是GPIO口的输入功能&#xff0c;和输出功能的配置略有区别。本次通过按键触发相应功能没有…

10.27复习day —— 药销系统分页前(上)

登陆界面 1.auto 水平方向 —— 占据尽量多的空间 margin:auto —— 水平居中 2.块状&#xff1a;block main、div、p 特点&#xff1a; 独占一行 水平方向占满父元素可用空间&#xff08;所以得设置宽度&#xff09; 垂直方向占据空间由其内容大小决定 行内&#xff1a;inlin…

clickhouse运维篇(三):生产环境一键生成配置并快速部署ck集群

前提条件&#xff1a;先了解集群搭建流程是什么样&#xff0c;需要改哪些配置&#xff0c;有哪些环境&#xff0c;这个文章目的是简化部署。 clickhouse运维篇&#xff08;一&#xff09;&#xff1a;docker-compose 快速部署clickhouse集群 clickhouse运维篇&#xff08;二&am…

快速入门kotlin编程(精简但全面版)

注&#xff1a;本文章为个人学习记录&#xff0c;如有错误&#xff0c;欢迎留言指正。 目录 1. 变量 1.1 变量声明 1.2 数据类型 2. 函数 3. 判断语句 3.1 if 3.2 when语句 4. 循环语句 4.1 while 4.2 for-in 5. 类和对象 5.1 类的创建和对象的初始化 5.2 继承 5…

云原生Istio基础

一&#xff0e;Service Mesh 架构 Service Mesh&#xff08;服务网格&#xff09;是一种用于处理服务到服务通信的专用基础设施层。它的主要目的是将微服务之间复杂的通信和治理逻辑从微服务代码中分离出来&#xff0c;放到一个独立的层中进行管理。传统的微服务架构中&#x…

【网页布局技术】项目五 使用CSS设置导航栏

《CSSDIV网页样式与布局案例教程》 徐琴 目录 任务一 制作简单纵向导航栏支撑知识点1&#xff0e;合理利用display:block属性2&#xff0e;利用margin-bottom设置间隔效果3&#xff0e;利用border设置特殊边框 任务二 制作简单横向导航栏任务三 制作带图片效果的横向导航栏任务…

银河麒麟v10 xrdp安装

为了解决科技被卡脖子的问题&#xff0c;国家正在大力推进软硬件系统的信创替代&#xff0c;对于一些平时对Linux操作系统不太熟练的用户来讲提出了更高的挑战和要求。本文以银河麒麟v10 24.03为例带领大家配置kylin v10的远程桌面。 最近公司为了配置信创开发新购了几台银河麒…

什么是x86架构,什么是arm架构

什么是 x86 架构&#xff1f; x86 架构是一种经典的指令集架构&#xff08;ISA&#xff09;&#xff0c;最早由英特尔在 1978 年推出&#xff0c;主要用于 PC、服务器等领域。 它是一种复杂指令集计算&#xff08;CISC&#xff09;架构&#xff0c;支持大量的复杂指令和操作&…

客户的奇葩要求—在CAN网络的基础上加入了CAN_FD的节点

1&#xff1a;客户的奇葩要求 最近的工作中&#xff0c;遇到了一个有点奇葩的事&#xff0c;客户需要开发一个系统&#xff0c;我们负责其中的一个ECU&#xff0c;这个系统采取的是经典11bit ID的CAN网络。 今天突然提了一个要求&#xff0c;说要在网络中&#xff0c;加入支持…