判断链表是否有环
快慢指针: 每循环一次两指针距离+1,相遇时两指针相差距离nb,b=环的长度。
l = 2s
l - s = nb
s = nb
sum = a + nb = a + s
- 时间复杂度 O(n)
- 空间复杂度 O(1)
class Solution {public:bool hasCycle(ListNode *head) {ListNode *slow = head;ListNode *fast = head;while (fast && fast->next) { // fast不能走一步和两步的情况slow = slow->next;fast = fast->next->next;if (slow == fast) return true;}return false;}};
链表中环的入口结点
#include <iostream>
#include <vector>
using namespace std;
struct ListNode {
int val;
struct ListNode *next;
ListNode(int n) : val(n), next(nullptr) {};
};
ListNode *solution(ListNode *p_head) {
if (p_head == nullptr) return nullptr;
ListNode *slow = p_head;
ListNode *fast = p_head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
// 快慢指针:每循环一次两个指针距离+1,相遇时两个指针走的距离相差nb
// 此时 假设慢指针走了s,快指针走了f,那么可以得到
// f = 2s, f-s = nb
// 所以s = nb 慢指针走的距离是环长度的n倍
// l = a + nb = a + s
// 要到达环入口结点要走的距离是a+nb,再往前走a的距离就可以到达入口结点
// 所以让快指针回到头结点与慢指针同时往前走,当相遇时两者都走了a的距离,此时为环的入口结点
if (fast == slow) {
fast = p_head;
while (fast != slow) {
fast = fast->next;
slow = slow->next;
}
return fast;
}
}
return nullptr;
}
int main() {
ListNode *p0 = new ListNode(0);
ListNode *p1 = new ListNode(1);
ListNode *p2 = new ListNode(2);
ListNode *p3 = new ListNode(3);
ListNode *p4 = new ListNode(4);
p0->next = p1;
p1->next = p2;
p2->next = p3;
p3->next = p4;
p4->next = p2;
ListNode *p_res = solution(p0);
cout << p_res->val << endl;
return 0;
}
