| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> LeetCode每日一练 —— 环形链表问题(面试四连问) -> 正文阅读 |
|
[数据结构与算法]LeetCode每日一练 —— 环形链表问题(面试四连问) |
🌟 前言 Wassup guys!我是Edison 😎 今天是 LeetCode 上的两道题: 141. 环形链表 和 142. 环形链表 II Let’s get it! 判断链表是否有环1. 题目描述
示例 1: 示例 2: 示例 3: 2. 思路分析这道题的思路很简单,还是用 快慢指针;
注意,如果链表没有环:
3. 动图演示准备两个指针 fast 和 slow,循环链表; slow 指针初始也指向 head,每次循环向前走一步; fast 指针初始指向 head,每次循环向前两步; 如果没有环,则快指针会抵达终点,如果有环,那么快指针会追上慢指针(动图演示👇) 4. 代码实现接口代码
提交结果 返回链表入环的第一个结点1. 题目描述
示例 1: 示例 2: 示例 3: 2. 思路分析
通过上面的第一道题,已经学会了判断链表是否有环了,那么接下来要找这个环的入口了。 假设从 头结点 到环形 入口节点 的节点数为 x。 环形 入口节点 到 fast 指针与 slow 指针 相遇节点 节点数为 y。 从 相遇节点 再到环形 入口节点 的节点数为 z。 (如图所示👇) 那么相遇时: slow 指针走过的节点数为:: x + y x + y x+y fast 指针走过的节点数: x + y + n ( y + z ) x + y + n (y + z) x+y+n(y+z),n 为 fast 指针在环内走了 n 圈才遇到 slow 指针, ( y + z ) (y+z) (y+z)为一圈内节点的个数。 因为 fast 指针是一步走两个节点,slow 指针一步走一个节点, 所以 f a s t 指针走过的节点数 = s l o w 指针走过的节点数 ? 2 fast 指针走过的节点数 = slow 指针走过的节点数 * 2 fast指针走过的节点数=slow指针走过的节点数?2,也就是👇 ( x + y ) ? 2 = x + y + n ( y + z ) (x + y) * 2 = x + y + n (y + z) (x+y)?2=x+y+n(y+z) 两边同时消掉一个 ( x + y ) (x+y) (x+y),化简得: x + y = n ( y + z ) x + y = n (y + z) x+y=n(y+z); 因为我们要找环形的入口,那么要求的是 x,因为 x 表示 头结点 到 环形入口节点 的距离。 所以我们要求 x ,将 x 单独放在左边: x = n ( y + z ) ? y x = n (y + z) - y x=n(y+z)?y; 在从 n ( y + z ) n(y+z) n(y+z) 中提出一个 ( y + z ) (y+z) (y+z) 来,整理公式之后为如下公式: x = ( n ? 1 ) ( y + z ) + z x = (n - 1) (y + z) + z x=(n?1)(y+z)+z ; 注意这里 n 一定是大于等于 1 的,因为 fast 指针 至少要多走一圈 才能相遇 slow 指针。 这个公式说明什么呢? 先拿 n 为 1 的情况来举例,意味着 fast 指针在环形里转了一圈之后,就遇到了 slow 指针了。 当 n 为 1 的时候,公式就化解为 x = z x = z x=z; 这就意味着,从头结点出发一个指针,从相遇节点也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是环形入口的节点。 也就是在相遇节点处,定义一个指针 index1,在头结点处定一个指针 index2。 让 index1 和 index2 同时移动,每次移动一个节点, 那么他们相遇的地方就是环形入口的节点。 (动图演示👇) 那么 n 如果大于 1 是什么情况呢?就是 fast 指针在环形转 n 圈之后才遇到 slow 指针。 其实这种情况和 n 为 1 的时候 效果是一样的,一样可以通过这个方法找到 环形的入口节点,只不过,index1 指针在环里 多转了 (n-1) 圈,然后再遇到 index2,相遇点依然是环形的入口节点。 3. 简化思路我们假设 快慢指针相遇 时,慢指针 slow 走了 k 步,那么快指针 fast 一定走了 2k 步(如图所示👇) fast 一定比 slow 多走了 k 步,这多走的 k 步其实就是 fast 指针在环里转圈圈,所以 k 的值就是环长度的「整数倍」。 假设 相遇点 距 环的起点 的距离为 m,(见下图👇)那么 环的起点 距头结点 head 的距离为 k - m,也就是说如果从 head 前进 k - m 步就能到达环起点。 如果从相遇点继续前进 k - m 步,也恰好到达环起点。因为结合上图的 fast 指针,从相遇点开始走 k 步可以转回到相遇点,那走 k - m 步肯定就走到环起点了(如图所示👇) 4. 代码实现接口代码
提交结果 扩展追问这道题的实现很简单,但是这里会有几个扩展问题,需要证明!
🍑 问题一
假设链表带环,两个指针最后都会进入环,快指针先进环,慢指针后进环。 当慢指针刚进环时,可能就和快指针相遇了,假设 快指针 和 慢指针 之间的距离为 N。 在他们移动的过程中,快指针往前走两步,慢指针走一步,此时,两个指针每移动一次,之间的距离就缩小 1 步,直到缩小为 0,那么就意味着他们相遇了,所以不会出现每次刚好是套圈的情况, 因此,在慢指针走到一圈之前,快指针肯定是可以追上慢指针的,即相遇。 🍑 问题二
在他们前进的过程中,快指针 每次走 3 步,慢指针 每次走 1 步,此时 快指针 肯定 先进环,慢指针 就 后进环。 假设 慢指针 进环时,快指针 和 慢指针 之间的距离为 N,又因为 快指针 每次走 3 步,慢指针 每次走 1 步,所以每走一次,他们之间的距离就缩小 2 。 此时要分 两 种情况: 1、如果 N 为偶数,那么他们之间的距离最终会缩小 0,也就是相遇。 2、如果 N 为奇数,那么他们之间的会减到 1,然后减到 负1,减到 负1 也就意味着他们之间的距离又变成了 C - 1(C 是环的周长),此时又分为 2 种情况; 2.1、若 C 为奇数,则 C - 1 为偶数,因为他们之间的距离一次缩小 2,所以他们还是会相遇; 2.2、若 C 为偶数,则 C - 1 为奇数,也就是说他们之间的距离还是奇数,那么他们永远都不会相遇。 总结:
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/25 22:36:44- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |