leetcode第141题:环形链表(C语言+引申问题全解)

解题思路:

定义一对快慢指针,slow指针每次走一步,fast指针每次走两步。当快指针入环时,慢指针只走了一半。

当slow指针入环时,fast指针已经在环内走了许多步。让他们两个继续走,直到相遇,可以证明链表是带环的。这是因为不带环的链表快慢指针不可能会相遇。

代码:

cs 复制代码
typedef struct ListNode listnode;
bool hasCycle(struct ListNode *head) {
    listnode* slow=head,*fast=head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast)
        {
            return true;
        }
    }
    return false;
}

代码到这里就已经解答完成了,是不是非常简单呢?

那么,我们就思考点更有意思的问题吧!

  1. 为什么快慢指针一定会相遇?没有可能错过,永远追不上?
  2. slow走一步,fast走3步、4步、5步或n步,结果也还是一样的吗?

哦莫,直击心灵的问题。

对问题1的思考与解答:

敲敲,数学课上课啦!

在快指针每次走两步,慢指针每次走一步的情况下,不可能会错过,一定能够追上。

假设slow指针进环时,fast指针与slow指针相差的距离为N。那么每次快慢指针移动过后,相差距离就减少1。这是因为慢指针每次走1步,快指针每次走2步,2 - 1 = 1。

|--------|--------|
| 移动次数 | 相差距离 |
| 0 | N |
| 1 | N-1 |
| 2 | N-2 |
| 3 | N-3 |
| 4 | N-4 |
| ...... | ...... |
| X-2 | 2 |
| X-1 | 1 |
| X | 0 |

**当相差距离为0时,代表两指针相遇了。**所以一定能追上。

对问题2的思考与解答:

通过问题1的解答,我们不难发现:快指针每次走的步数 - 慢指针每次走的步数 = N每次的减少量

所以假设快指针现在每次走3步,慢指针不变,那么N每次减少2。这时候,就出现了一个问题。

N为偶数时,每次减少2,最后能得到N=0的结果。然而,当N为奇数时,最后N= -1。

此处的**-1 意为fast指针已经越过了slow指针** (如下图所示),假设整个环的大小为C,那么N 就变为了 C-1

此时,就可以把C-1看成是N。如果C-1为偶数,那么最后就能得到N=0的结果;但如果C-1为奇数,那么结果还是-1,又变成了C-1,而C-1永远是奇数,因此一定无法相遇。

总结("fast每次走2步,slow每次走1步"的情况):

  • 如果N为偶数,那么第一轮slow和fast就能相遇
  • 如果N为奇数,第二轮一开始fast和slow相差C-1
  1. 若C-1是偶数,那么第二轮就追上了
  2. 若C-1是奇数,那么就永远也追不上

所以,同时存在C是偶数且N是奇数,那么就永远也追不上。

数学论证:

假设进环以前,slow与fast都需要走L的路程。那么当slow进环时,fast已经走了 L + x*C + C - N(x为fast在环里面转了几圈)

因为slow进环时,fast走的距离是slow3倍,所以slow走了L,fast走了3L。

综上所述,得到公式:3L = L + x*C +C - N

即2L = (x+1)*C - N。2L一定是偶数,要论证的是C是偶数且N是奇数时,永远追不上(可以使用反证法)。把这种情况代入公式,C为偶数,那么(x+1)*C一定是偶数;N为奇数,因此右式一定为奇数( 偶数-奇数 一定是奇数),相互矛盾。所以C是偶数且N是奇数时,永远追不上。证毕。

除了这种情况外,其他情况下fast都是能追上slow的。

更多情况:

假设fast每次走4步,slow每次走1步,那么情况就与上文所讲解的形同。继续通过判断是奇数还是偶数,以及列出判断公式就能解决问题。**只是情况要分为了两指针错过后,相距C-2还有相距C-1两种情况(N和3取模即可有不同结果)。**请大家也来试着做做吧!

相关推荐
一直学习永不止步32 分钟前
LeetCode题练习与总结:最长回文串--409
java·数据结构·算法·leetcode·字符串·贪心·哈希表
Rstln1 小时前
【DP】个人练习-Leetcode-2019. The Score of Students Solving Math Expression
算法·leetcode·职场和发展
珹洺1 小时前
C语言数据结构——详细讲解 双链表
c语言·开发语言·网络·数据结构·c++·算法·leetcode
几窗花鸢2 小时前
力扣面试经典 150(下)
数据结构·c++·算法·leetcode
.Cnn2 小时前
用邻接矩阵实现图的深度优先遍历
c语言·数据结构·算法·深度优先·图论
2401_858286112 小时前
101.【C语言】数据结构之二叉树的堆实现(顺序结构) 下
c语言·开发语言·数据结构·算法·
寻找码源3 小时前
【头歌实训:利用kmp算法求子串在主串中不重叠出现的次数】
c语言·数据结构·算法·字符串·kmp
带多刺的玫瑰5 小时前
Leecode刷题C语言之统计不是特殊数字的数字数量
java·c语言·算法
陌小呆^O^5 小时前
Cmakelist.txt之win-c-udp-server
c语言·开发语言·udp
时光の尘5 小时前
C语言菜鸟入门·关键字·float以及double的用法
运维·服务器·c语言·开发语言·stm32·单片机·c