leetcode_141 环形链表
1. 题意
给你一个链表的头节点 head ,判断链表中是否有环。
2. 题解
2.1 哈希表
直接遍历这个链表,在哈希表中是
否存在这样一个节点了,如果已经存在了说明链表有环;
否则将这个节点放入哈希表继续往后处理。
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:bool hasCycle(ListNode *head) {bool have_circle{ };unordered_set<ListNode *> us{};ListNode *cur = head;while ( cur ) {if ( us.find(cur) != us.end()) {have_circle = true;break;}us.insert( cur );cur = cur->next;}return have_circle;}
};
2.2 快慢指针
快指针每次走两步,
慢指针每次走一步。
如果有环,它们肯定能相遇。
其实等价于
总是存在t
,使得
(a+t)≡(b+2t)(modM)a≡b+t(modM)(a+t) \equiv (b+2t) \quad (\ \bmod\ M) \\ a \equiv b+t \quad ( \bmod \ M) (a+t)≡(b+2t)( mod M)a≡b+t(mod M)
取t=(a−b+M)modMt=(a-b + M) \bmod Mt=(a−b+M)modM即可。
当然这个问题其实可以推广一下,
假设在a
位置的可以走s1
步,b
位置的可以走s2
步。
那么它们是否在大小为M
的环内相遇就变成了求t
满足
线性同余方程
a+s1t≡b+s2t(modM)a−b≡(s2−s1)t(modM)a+s_1t \equiv b+s_2t \quad (\ \bmod\ M)\\ a-b \equiv (s_2-s_1)t \quad (\ \bmod\ M) a+s1t≡b+s2t( mod M)a−b≡(s2−s1)t( mod M)
这个方程要有解,必然要满足
gcd(s2−s1,M)∣a−b\gcd(s_2-s_1,M) \mid a-b gcd(s2−s1,M)∣a−b
上代码
也可以用相对速度来理解,一个指针相对另一个指针的速度是1
,
在环内的距离必然固定,因此它们必然相遇。
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:bool hasCycle(ListNode *head) {if ( NULL == head)return false;ListNode *slow = head;ListNode *fast = slow->next;while ((slow != fast) && fast && fast->next) {slow = slow->next;fast = fast->next->next;}return slow == fast;}
};
参考
leetcode
0x3f