算法从零到精通 (一) ~ 快慢双指针

news2024/11/15 19:57:41

1. 前言

快慢双指针是一种常用的算法技巧,通常用于解决涉及链表或数组的问题。它的基本思想是使用两个指针,一个移动速度快(快指针),一个移动速度慢(慢指针),来解决特定的问题。这两个指针通常从序列的起始位置开始,并以不同的步伐向前移动,直到达到特定的条件为止。

  • 快慢双指针是指在算法处理过程中,使用两个指针,分别从序列的起始位置出发,按照不同的步伐向前移动,直到满足某种条件。通常快指针的移动速度比慢指针快,这样可以加快算法的执行速度。
  • 判断链表是否有环:快指针每次移动两步,慢指针每次移动一步,如果存在环,快指针最终会追上慢指针。

  • 找到链表的中间节点:快指针每次移动两步,慢指针每次移动一步,当快指针到达链表末尾时,慢指针所在位置即为中间节点。

  • 移除排序数组中的重复项:使用快慢指针,当快指针遇到不同的元素时,将其复制到慢指针位置,然后慢指针前进一步。

 2. 我对快慢指针的理解

1. 数组划分

  1. cur:从左到右扫描数组,遍历数组(快指针)
  2. dest:已处理的区间内,非零元素的最后一个位置
  3. cur(快指针)遇到符合题意的值,把他加入这个区间。一般是先dest++然后和cur交换

如何做到维护该区间一直到结束,是解题的关键。

// 符合题意           不符合题意            未处理元素
// [0~dest]        [dest + 1 ~ cur]       [cur + 1 ~ n]

达到最终的目的就是持续这三块区域的关系

2. 判断是否成环

快指针每次移动两步,慢指针每次移动一步,如果存在环,快指针最终会追上慢指针。

3 例题分析

3.1 移动零 (数组划分)

 

public void moveZeroes(int[] nums) {
        // 符合题意(非0元素)    不符合题意(0)    未处理元素
        // [0~dest]        [dest + 1 ~ cur]       [cur + 1 ~ n]
        // 要想维护上面的关系到结束,必须让cur遇到符合题意的和dest后一个元素(不符合题意的交换),
        //                        然后让dest++(扩大符合题意的范围),继续维护该区间
        int n = nums.length, cur = 0, dest = -1;
        while(cur != n){
            if (nums[cur] != 0){//遇到符合题意的,交换来维持三个区间关系
                dest++;
                int temp = nums[dest];
                nums[dest] = nums[cur];
                nums[cur] = temp;
            }
            cur++;
        }
    }

3.2 去重

下面的图,就是我对上题一步步的分析:

只要一直维持这三个区域到结束,就可以解答本题。

如何维持,就成了解答本题的关键。

    /**
     * 思路分析:
     * 1. dest(慢指针):确定没有重复元素的最后一个位置, cur(快指针):扫描完的最后一个位置
     * 2. 通过比较快慢指针的内容确定是否重复 (因为非严格递增,相同的都是连续的)
     * 3. 遇到一个不重复元素,就是符合[0 ~ dest]区间,就和dest+1不符合该区间的交换位置
     *
     * @param arr
     * @return
     */
    public static int[] arrayDeduplication(int[] arr) {
        //默认第一个元素不重复
        int n = arr.length, dest = 0, cur = 1;
        while (cur < n) {
            if (arr[cur] != arr[dest]) {//找到一个不符合题意的
                dest++;
                int temp = arr[dest];
                arr[dest] = arr[cur];
                arr[cur] = temp;
            }
            cur++;
        }
        return Arrays.copyOf(arr,dest + 1);
    }

    public static void main(String[] args) {
        int[] arr = {1, 1, 4, 4, 5, 6, 7, 7, 8, 8, 8, 8, 8};
        int[] distinction = arrayDeduplication(arr);
        System.out.println(Arrays.toString(distinction));
        System.out.println(Arrays.toString(arr));
    }

3.3 复写零

思路分析:

因为正序会造成覆盖,比如 0 1 2  正序读0索引->会变成 0 0 1,下次读1索引就被覆盖了。 

  1. 先判断要舍弃的元素。(因为要复写,数组大小不变总要舍去)
  2. 从后往前复写,0写两次,其余写一次
  3. 判断临界情况,防止最后一个为0且数组长度不够

剩下的内容代码有详细的注释。 

  // 正着写会被覆盖,因此倒序,倒序要确定复写舍弃的元素(复写位置),最后处理临界:cur越界
    // 1. 通过 0 cur移动两步 和 非0 cur移动一步,确定从dest位置开始复写
    // 2. 倒序开始写,dest读取到0复写 cur写两遍  非0  cur写一遍
    // 3. 处理临界:最后一个修改成0, dest-2  cur-1
    public static void duplicateZeros(int[] arr) {
        //因为读完写,所以dest(慢指针)为0,cur为-1
        int n = arr.length, dest = 0, cur = -1;
        //1.确定dest位置
        while(dest < n){
            if (arr[dest] == 0){//写两边
                cur++;cur++;
            }else {//写一遍
                cur++;
            }
            if (cur >= n - 1) break;//写到最后或者写过(最后一个为0),dest就不需要读了
            dest++;
        }
        //3. 处理临界
        if (cur == n){
            arr[n - 1] = 0;
            cur--;cur--;
            dest--;
        }
        //此时dest后面就是舍弃的元素
        //2. 倒序复写
        while(dest >= 0){
            if (arr[dest] == 0){//写两边
                arr[cur--] = 0;
                arr[cur--] = 0;
            }else {//写一遍
                arr[cur--] = arr[dest];
            }
            dest--;
        }
    }

 

3.4 快乐数(判断环)

 通过数字的取平方和来模拟移动,取一次移动一步,俩次移动两步,这样就可以模拟链表。和判断链表是否有环,原理一样,仅需判断链表中元素是否为1即可。

为什么是必定有环的呢???

原因就是鸽巢原理,所以数据范围有限的情况下,必定有环。5个人有6个糖,必定有一个人是有两个糖即以上的。

public class Test3 {
    //通过数来模拟指针移动,和判断链表是否有环,原理一样
    //仅需判断链表中元素是否为1即可
    //要么是1,要么无限循环的原因就是鸽巢原理,所以数据范围有限的情况下,必定有环
    public boolean isHappy(int n) {
        int slow = n, fast = bitSum(n);
        while(slow != fast){
            slow = bitSum(slow);
            fast = bitSum(bitSum(fast));
        }
        return slow == 1;
    }

    //求一个数各个元素的平方和,相当于移动一次
    private int bitSum(int num){
        int sum = 0;
        while(num != 0){
            int t = num % 10;
            sum += t * t;
            num /= 10;
        }
        return sum;
    }
}

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

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

相关文章

【高可用】利用AOP实现数据库读写分离

最近项目中需要做【高可用】数据库读写分离相关的需求&#xff0c;特地整理了下关于读写分离的相关知识。项目中采用4台数据库&#xff1a;1个master&#xff0c;2个slave&#xff0c;1个readOnly&#xff0c;其中master数据库会自动定时同步到readOnly节点。可以通过中间件(Sh…

Mysql —— 事务

目录 什么是事务&#xff1f; 两种方式实现事务&#xff1a; 方法一 方法二&#xff1a; 事务四大特性(简称ACID) 并发事务问题&#xff08;面试题&#xff09; 事务隔离级别 什么是事务&#xff1f; 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff…

跨域浏览器解决前端跨域问题

1.问题背景 这是一种属于非主流的解决跨域的方案&#xff0c;但是也是可以正常使用而且比较简单的。如果需要使用主流的解决前端跨域方案&#xff0c;请参考这篇文章。 我这边其实是优先建议大家使用主流的跨域方案&#xff0c;如果主流的实在不行&#xff0c;那么就使用跨域…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 图像物体的边界(200分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线…

scratch绘制十个圆 2024年6月中国电子学会图形化编程 少儿编程 scratch编程等级考试三级真题和答案解析

目录 scratch绘制十个圆 一、题目要求 1、准备工作 2、功能实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、实现流程 1、案例分析 2、详细过程 四、程序编写 五、考点分析 六、推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程 5、…

css气泡背景特效

css气泡背景特效https://www.bootstrapmb.com/item/14879 要创建一个CSS气泡背景特效&#xff0c;你可以使用CSS的伪元素&#xff08;:before 和 :after&#xff09;、border-radius 属性来创建圆形或椭圆形的“气泡”&#xff0c;以及background 和 animation 属性来设置背景…

mysql 先子查询过滤再联合 和 先联合再过滤 执行效率问题

执行顺序 先子查询过滤再联合 SELECT XXX FROM(select * from edw_data_dyd.overrun_offsite_info WHERELENGTH( VEHICLE_ID ) > 12 AND CREATED_TIME > DATE_ADD(NOW(),INTERVAL -1 HOUR)AND CREATED_TIME < NOW()AND VEHICLE_ID not like %无车牌%AND VEHICLE_I…

华为ICT大赛之ensp软件BGP原理与配置

BGP基础 1.用于不同自治系统AS(autonomous system)之间动态交换路由信息&#xff1b; BGP取代EGP(exterior gateway protocol)外部网关协议&#xff0c;BGP在其发布路由信息基础上可以进行路由优选&#xff0c;高效处理路由信息&#xff1b; AS:同一组织管理下&#xff0c;使…

全面解析 SnowNLP:中文文本处理、情感分析

1 前言 SnowNLP 是一个专门用于处理中文文本的 Python库。功能包括&#xff1a; 分词情感分析关键词提取文本分类拼音转换繁体转简体词相似度计算等 snownlp0.12.3测试环境&#xff1a;Python3.10.9 2 分词 中文分词&#xff08;Character-Based Generative Model&#xf…

WEB渗透Web突破篇-前端突破

逻辑漏洞 1.任意用户注册 2.用户名枚举 3.爆破用户名&#xff0c;密码 4.用户名注入 5.万能密码 6.用户名Xss 7.修改返回包信息&#xff0c;登入他人账户 8.修改cookie中的参数&#xff0c;如user,adminid等 9.HTML源码、JS等查看信息搜集那一章 10.后台登录参数修改…

MSPM0G3507学习笔记1:开发环境_引脚认识与点灯

今日速通一款Ti的单片机用于电赛&#xff1a;MSPM0G3507 这里默认已经安装好了Keil5_MDK 首先声明一下: 因为是速成&#xff0c;所以需要一定单片机学习基础&#xff0c;然后我写的也不会详细&#xff0c;这个专栏的笔记也就是自己能看懂就行的目标~~~ 文章提供测试代码解…

Go: IM系统分布式架构方案 (6)

分布式部署可能遇到的问题 常见 nginx 反向代理方案 假设按照上述架构方案来A用户接入后connA(ws客户端) 由节点1来维护B用户接入后connA(ws客户端) 由节点2来维护流程: A->B 发信息: A -> connA -> 分析处理 -> connB -> B实际上&#xff0c;上述流程是没有办法…

C++学习笔记03-对象和类(问题-解答自查版)

前言 以下问题以Q&A形式记录&#xff0c;基本上都是笔者在初学一轮后&#xff0c;掌握不牢或者频繁忘记的点 Q&A的形式有助于学习过程中时刻关注自己的输入与输出关系&#xff0c;也适合做查漏补缺和复盘。 本文对读者可以用作自查&#xff0c;答案在后面&#xff0…

1 深度学习网络DNN

代码来自B站up爆肝杰哥 测试版本 import torch import torchvisiondef print_hi(name):print(fHi, {name}) if __name__ __main__:print_hi(陀思妥耶夫斯基)print("HELLO pytorch {}".format(torch.__version__))print("torchvision.version:", torchvi…

C++(week13): C++基础: 标准模板库 STL

文章目录 零、标准模板库 STL一、容器 (Container)1.序列式容器(1)vector2.五种遍历10.vector的迭代器失效问题 (2)deque(3)list 2.关联式容器(1)set4.set的查找(2)find() 8.set中存储自定义类型&#xff1a;三种方法 (2)multiset7.multiset的特殊操作&#xff1a;bound系列函数…

LeetCode/NowCoder-二叉树OJ练习

励志冰檗&#xff1a;形容在清苦的生活环境中激励自己的意志。&#x1f493;&#x1f493;&#x1f493; 目录 说在前面 题目一&#xff1a;单值二叉树 题目二&#xff1a;相同的树 题目三&#xff1a;对称二叉树 题目四&#xff1a;二叉树的前序遍历 题目五&#xff1a;另…

Python | Leetcode Python题解之第275题H指数II

题目&#xff1a; 题解&#xff1a; class Solution:def hIndex(self, citations: List[int]) -> int:n len(citations)left 0; right n - 1while left < right:mid left (right - left) // 2if citations[mid] > n - mid:right mid - 1else:left mid 1retur…

C语言之2048小游戏理解分析

目录 游戏程序思维导图&#xff1a; ​编辑 功能介绍&#xff1a; 代码管理&#xff1a; 主函数&#xff1a; 头文件&#xff1a; 游戏程序思维导图&#xff1a; 功能介绍&#xff1a; 按键W --------------- 向上 按键A --------------- 向左 按键S --------------- 向…

科技云报道:算网筑基AI注智,中国联通如何讲出AI时代的“新故事”?

科技云报道原创。 AI从未停止进化&#xff0c;也从未停止给人类带来惊喜。 从ChatGPT代表的文生文、Dall-E代表的文生图&#xff0c;到Sora代表的文生视频&#xff0c;Suno为代表的文生音乐&#xff0c;生成式AI的“暴力美学”持续突破内容生产的天花板&#xff0c;大模型技术…

【黑马java基础】特殊文件,日志

目录 特殊文件&#xff1a;Properties属性文件特点、作用使用Properties读取属性文件里的键值对数据使用properties把键值对数据写到属性文件中去案例 特殊文件&#xff1a;XML文件概述读取XML文件中的数据把数据写出到XML文件中去补充知识&#xff1a;约束XML文件的编写[了解]…