使用双指针解决链表题(好好好)

使用双指针解决链表题(好好好)

发癫:  

  你知道吗,力扣倒着读就是库里(扣力)哦!

  啦啦啦 啦啦 啦啦啦,CodeLeet,  CodeLeet,  CodeLeet CodeLeet !

                               

正文:

  ok,废话少说,这是一篇初出茅庐的小白被链表题整疯后对双指针解决链表题的见解。

  双指针,即使用两个指针去解决问题。能用两个指针解决的问题通常用一个指针也能解决,但是双指针相比于单指针,在时间复杂度和空间复杂度方面都占优势。

(来源:LeetCode)

  像这一题,使用单指针并重新开辟一个链表即使是一个小白(我第一次就是这样写的)也可以很轻松地解答出来;使用双指针,假设为 p1, p2p2 用于判断“值”是否符合,且保证 p2 一直是 p1 的下一位,用来决定 p1 是顺序移动还是跳过(还可以设定一个哨兵位来辅助)。可以将空间复杂度降为O(1),虽然不是什么很强的优化,但是起码看起来比用单指针厉害呀!(滑稽)

  什么?!双指针太麻烦,🐕都不用?!不不不,单指针的上限可远不如双指针,接下来登场的是将双指针优势发挥到极致的——快慢指针

(来源:LeetCode)

  这一题使用单指针同样能解决,就是先遍历一遍链表获取链表长度,然后再遍历一次(只遍历一遍);如果使用快慢指针,快指针一次走两步,慢指针一次走一步,当快指针到尾节点时,慢指针刚好到达中间节点,听懂掌声!!!

(来源:LeetCode)

  刚才那题单链表还有发挥空间,但这一题用单链表一走就是一辈子了。

  那么用快慢指针是个什么样的解法呢?这题其实还是比较吃数学思维的:这道题要分两个部分来解决,一是判断是否有环,二是找进入环的节点。

  一、判断:

  依旧是快指针走两步,慢指针走一步,当它们两个能够相遇,就说明这个链表中有环。

  如果链表没有环快慢指针当然是不可能相遇的,关于如何证明有环必定相遇,不妨把两个指针入环之后的运动当作追击运动。当慢指针入环,快指针必定在环中已经运动一段时间,假设此时快指针追击慢指针所需要经过的距离为N,因为快指针走两步,慢指针才走一步,那么每次它们的距离缩短一个节点,当运动N次时,快指针追上慢指针。

  二、找入环节点:

  这里同样需要两个指针,一个指针从原链表的头节点开始每次一步,一个指针从前面快慢指针相遇的节点开始同样每次一步,当这次的两个指针相遇,相遇的节点即为入环节点。

  这一步的证明就比较麻烦了。

  首先需要清楚,当慢指针和快指针相遇时,慢指针必然不可能完全绕环运动过一周。因为假设环的长度为 C ,当慢指针运动 C 的一半时,快指针至少已经绕过环一周(即一个完整的 C ),当慢指针开始完成剩下的一半路程时,无论快指针在哪,都一定可以在慢指针完成一圈之前追上它。

  然后,不妨假设从头节点到入环节点的距离为 A ,从入环节点按顺序抵达相遇节点的距离为 B ,慢指针走过的总路程则为 A + B ,快指针可能绕环 n 周,它走过的路程为 A + B + n * C 。根据它们之间的路程关系,有:

                                     

  即 A  = n * C - B,左边是从头节点开始运动的指针走到入环节点所要走的路程,右边可以看作从相遇节点开始的指针绕了环 n 圈之后再次回到入环节点的路程。

   以上的快慢指针都是动态的,还是很吃脑子的的呀!最后再讲一个静态的,比较简单,缓一缓。

  如果能写出前面的题目,这一题简直就是小儿科啦。

  同样使用到两个指针,但是把这两个指针分别叫做前指针和后指针更好理解。一开始两个指针都指向头节点,然后根据 k 的不同,让前指针先运动,k = 1 运动一步,k = 2 运动两步,以此类推。之后前指针和后指针同时运动,当前指针为空,后指针指向的节点就是要找的节点。

总结:

  最后总结一下:时间复杂度方面, 由于比单指针多一个指针,所以在需要遍历链表时,双指针的比单指针更具优势,甚至可以达到 一加一大于二 的效果。空间复杂度更不用说,能把O(n)降为O(1),是一个巨大的提升。双指针还能让链表的拼接、分割、合并等操作逻辑更清晰,甚至可以在一次遍历中同时完成 “遍历、判断、修改” 等多步操作,避免重复遍历带来的性能损耗。

  双指针的讲解到此结束。

Read more

【 C/C++ 算法】入门动态规划-----路径问题(以练代学式)

【 C/C++ 算法】入门动态规划-----路径问题(以练代学式)

>每日激励:“不设限和自我肯定的心态:I can do all things。 — Stephen Curry” 绪论 : 本章是动态规划的第二篇,本章将开始二维的动态规划,在二维中的动态规划本质和一维的分析来说差不太多,只不过状态表示从一维变成了二维,而在二维上所能管理的状态就从一维的两个变成了二维的三个,也就是x轴,y轴,数组中的值。若没看了解过动规算法,我强烈建议先看第一篇blog,因为当你看完第一篇你就对动规基本认识了,其中也就能认识到它的五步骤分析法,这里也就不扩充说明而是直接使用了 ———————— 早关注不迷路,话不多说安全带系好,发车啦(建议电脑观看)。 路径问题🛣️ 本章主要还是在二维数组中的进行的动态规划: 同样还是五步走:状态表示、状态方程、初始化、移动方向、返回结果 1. 其中在二维中状态表示就会和一位略有不同,不同本质一样: 从以 i 结尾.,… ==》从左上角到达 i j 位置,… 1. 当然在最后一题中发现上面这种常规方法实现不通,因为状态方程会受后面状态影响 2.

By Ne0inhk
【大数据存储与管理】分布式文件系统HDFS:05 HDFS存储原理

【大数据存储与管理】分布式文件系统HDFS:05 HDFS存储原理

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈大数据技术原理与应用 ⌋ ⌋ ⌋专栏系统介绍大数据的相关知识,分为大数据基础篇、大数据存储与管理篇、大数据处理与分析篇、大数据应用篇。内容包含大数据概述、大数据处理架构Hadoop、分布式文件系统HDFS、分布式数据库HBase、NoSQL数据库、云数据库、MapReduce、Hadoop再探讨、数据仓库Hive、Spark、流计算、Flink、图计算、数据可视化,以及大数据在互联网领域、生物医学领域的应用和大数据的其他应用。 【GitCode】专栏资源保存在我的GitCode仓库:https://gitcode.com/Morse_Chen/BigData_principle_application。 文章目录 * 一、数据的冗余存储 * 二、数据存取策略 * (一)数据存放 * (二)数据读取 * (三)数据复制 * 三、数据错误与恢复 * (一)

By Ne0inhk
优选算法——滑动窗口2

优选算法——滑动窗口2

优选算法——滑动窗口 1.1004. 最大连续1的个数 III 题目描述 思路分析 这道题的核心是:找一个最长的子数组,其中最多包含 k 个 0。 经典的 滑动窗口 问题。 为什么用滑动窗口? * 我们需要连续区间 → 滑动窗口天然适合 * 窗口内维护「0 的个数 ≤ k」这个约束 * 窗口扩张:右指针右移,遇到 0 就计数 * 窗口收缩:当 0 的个数超过 k,左指针右移直到满足条件 算法流程 1. 初始化:left = 0, zeroCount = 0, maxLen = 0 2. 遍历数组,right 指针右移: -

By Ne0inhk
Python | XGBoost+SHAP可解释性分析回归预测及可视化算法

Python | XGBoost+SHAP可解释性分析回归预测及可视化算法

立个flag,这是未来一段时间打算做的Python教程,敬请关注。 1 数据及应用领域 我的程序中给出数据data.xlsx(代码及数据见文末),10 列特征值,1 个目标值,适用于各行各业回归预测算法的需求,其中出图及数据自动保存在当前目录,设置的训练集与预测集的比例为 80%:20%。 (1)地球科学与环境科学 * 遥感反演:利用多源遥感数据预测水体深度、土壤湿度、植被指数、叶面积指数等。 * 气象与气候研究:预测降水量、气温、风速、风向等连续气象变量。 * 水文与水资源管理:河流流量、地下水位、径流量预测。 * 环境污染监测:空气质量指数、PM2.5/PM10浓度、重金属污染水平预测。 * 地质与矿业:预测矿区地表沉降、地裂缝发展趋势,或矿产储量评估。 (2)生物学与医学 * 生态学:预测物种分布密度、群落生物量或生态环境因子变化。 * 公共卫生:基于环境、

By Ne0inhk