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

目录

  • 一、双指针简介
    • 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;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Pandas DataFrame学习补充

1. 从字典创建&#xff1a;字典的键成为列名&#xff0c;值成为列数据。 import pandas as pd# 通过字典创建 DataFrame df pd.DataFrame({Column1: [1, 2, 3], Column2: [4, 5, 6]}) 2. 从列表的列表创建&#xff1a;外层列表代表行&#xff0c;内层列表代表列。 df pd.Da…

二、Go快速入门之数据类型

&#x1f4c5; 2024年4月27日 &#x1f4e6; 使用版本为1.21.5 Go的数据类型 &#x1f4d6;官方文档&#xff1a;https://go.dev/ref/spec#Types 1️⃣ 布尔类型 ⭐️ 布尔类型只有真和假,true和false ⭐️ 在Go中整数0不会代表假&#xff0c;非零整数也不能代替真&#…

Springboot整合原生ES依赖

前言 Springboot整合依赖大概有三种方式&#xff1a; es原生依赖&#xff1a;elasticsearch-rest-high-level-clientSpring Data ElasticsearchEasy-es 三者的区别 1. Elasticsearch Rest High Level Client 简介: 这是官方提供的 Elasticsearch 客户端&#xff0c;支持…

Spark,Anconda在虚拟机实现本地模式部署

如果想要了解模式的概念部分&#xff0c;以及作用请看&#xff1a; Spark学习-CSDN博客 一.在虚拟机安装spark cd /opt/modules 把Anconda和Spark安装包拖拽进去&#xff1a; 解压&#xff1a; tar -zxf spark-3.1.2-bin-hadoop3.2.tgz -C /opt/installs 重命名&#x…

Javaee:阻塞队列和生产者消费者模型

文章目录 什么是阻塞队列java中的主要阻塞队列生产者消费者模型阻塞队列发挥的作用解耦合削峰填谷 模拟实现阻塞队列put方法take方法生产者消费者模型 什么是阻塞队列 阻塞队列是一种支持阻塞操作的队列&#xff0c;在多线程中实现通线程之间的通信协调的特殊队列 java中的主…

[网络协议篇] UDP协议

文章目录 1. 简介2. 特点3. UDP数据报结构4. 基于UDP的应用层协议5. UDP安全性问题6. 使用udp传输数据的系统就一定不可靠吗&#xff1f;7. 基于UDP的主机探活 python实现 1. 简介 User Datagram Protocol&#xff0c;用户数据报协议&#xff0c;基于IP协议提供面向无连接的网…

使用 three.js 渲染个blender模型

首先需要一个扫描模型&#xff0c;工业上有专门的设备去采集模型的面然后通过建模软件去处理外表面贴图 我们这里取了一个ford汽车的发动机模型 为了让three.js能够使用&#xff0c;使用blender把模型保存为glb格式 为了让页面加载glb模型更快&#xff0c;需要对模型文件进行压…

jade 0919 | 提取自TVBox的直播盒子,频道丰富高清

jade电视直播app覆盖央视全频道和各大卫视&#xff0c;各地地方台也能一网打尽&#xff0c;随时随地看高清电视。各卫视台覆盖广泛&#xff0c;包括浙江电视台、湖南卫视、江苏卫视、东方卫视等全部卫视台&#xff0c;最新内容先一步掌握。拥有广东、北京、风云足球等热播体育频…

Oracle视频基础1.3.2练习

1.3.2 看 Oracle 实例是否启动 ps -ef | grep oracle备份已有的数据库文件到 old 文件夹&#xff0c;用 sample pfile 手动创建新的数据库文件 pfile mkdir old,mv * old,ls,cd old,cp init.ora …/initwilson.ora编辑 pfile&#xff0c;修改 db_name&#xff0c;db_block_siz…

“中信同业+”焕新升级 锚定数字金融新主线,做实金融“五篇大文章”

9月20日&#xff0c;“中信同业”升级发布会及生物多样性债券指数发布在京顺利举办&#xff0c;此次活动以“做强数字金融 服务实体经济”为主题&#xff0c;由中信金控指导&#xff0c;中信银行主办&#xff0c;中信各金融子公司联合承办。来自银行、证券、保险、基金等行业百…

重学SpringBoot3-Spring WebFlux之HttpHandler和HttpServer

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-Spring WebFlux之HttpHandler和HttpServer 1. 什么是响应式编程&#xff1f;2. Project Reactor 概述3. HttpHandler概述3.1 HttpHandler是什么3.2 Http…

全桥PFC电路及MATLAB仿真

一、PFC电路原理概述 PFC全称“Power Factor Correction”&#xff08;功率因数校正&#xff09;&#xff0c;PFC电路即能对功率因数进行校正&#xff0c;或者说是能提高功率因数的电路。是开关电源中很常见的电路。功率因数是用来描述电力系统中有功功率&#xff08;实际使用…

【音视频 | ADPCM】音频编码ADPCM详细介绍及例子

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

python读取视频并转换成gif图片

1. 安装三方库 moviepy 将视频转换成gif&#xff0c;需要使用 moviepy库 确保已经安装了moviepy库 pip install moviepy2. 代码实现&#xff1a; from moviepy.editor import VideoFileClipmyclip VideoFileClip("video.mp4") myclip2 myclip.subclip(0, 10).re…

人工智能原理实验二:搜索方法

一、实验目的 本实验课程是计算机、智能、物联网等专业学生的一门专业课程&#xff0c;通过实验&#xff0c;帮助学生更好地掌握人工智能相关概念、技术、原理、应用等&#xff1b;通过实验提高学生编写实验报告、总结实验结果的能力&#xff1b;使学生对智能程序、智能算法等…

在Centos7.9服务器上使用LVM方式挂载磁盘以及Windows磁盘性能测试与Linux磁盘性能测试命令hdparm详细

一、在Centos7.9服务器上使用LVM方式挂载磁盘 在磁盘分区挂载之前&#xff0c;先使用lsblk命令查看磁盘信息&#xff0c;未分区挂载的磁盘sdb只有disk类型没有part类型。40G的硬盘sda已经分了两个区sda1、sda2。而sdb磁盘下并没有分区信息&#xff0c;说明还没有分区。磁盘分区…

dicom基础:乳腺影像方位信息介绍

目录 一、轴位 (CC, Craniocaudal) 二、侧位 (Lateral) 三、侧斜位 (MLO, Mediolateral Oblique) 四、不同的拍摄方位的乳腺影像展示 1、RCC&#xff08;Right Craniocaudal&#xff09; 2、LCC&#xff08;Left Craniocaudal&#xff09; 3、RMLO&#xff08;Right Medio…

uniapp 报错Invalid Host header

前言 在本地使用 nginx 反向代理 uniapp 时&#xff0c;出现错误 Invalid Host header 错误原因 因项目对 hostname 进行检查&#xff0c;发现 hostname 不是预期的&#xff0c;所以&#xff0c;报错 Invalid Host header 。 解决办法 这样做是处于安全考虑。但&#xff0…

10个领先的增强现实平台【AR】

增强现实 (AR) 被描述为一种通过计算机生成的内容增强现实世界的交互式体验。 使用软件、应用程序和硬件&#xff08;例如 AR 眼镜&#xff09;&#xff0c;AR 能够将数字内容叠加到现实环境和物体上。早在 2024 年&#xff0c;许多像 Apple 这样的公司就已进入 VR/AR 市场&am…

匹配——rabin_karp是怎么滚动的?

滚动散列函数 接前面用例公式滚动last_pos第三行第二行第一行证明后话接前面 匹配——散列法里面只说前一个字符乘以128再对72057594037927931求模,答案乘以128加后一个字符再对72057594037927931求模。对应代码: hash_s = (DOMAIN * hash_s + ord(s[i])) % PRIME用例 还是…