环形链表——双指针
原题在这里:
概述题意:
给定一个可能有环的链表,如果有环则返回第一个环节点,否则null
低配hash处理:
class Solution { map<ListNode *, int> mp; public: ListNode *detectCycle(ListNode *head) { if (!head || mp[head] == 1) return head; mp[head] = 1; return detectCycle(head->next); } };
高配双指针:
class Solution { public: ListNode *detectCycle(ListNode *head) { ListNode *p = head, *q = head; while (p != nullptr) { q = q->next; if (p->next == nullptr) return nullptr; p = p->next->next; if (p == q) { //重新走一遍 p = head; while (p != q) { p = p->next; q = q->next; } return p; } } return nullptr; } };
analyse:
大概:
s快=s慢+n*b,s快=s慢*2,故得:s慢=n*b
如果有环,快指针与慢指针相遇时候,快指针一定比慢指针多走n倍环的长度b,又有快指针路径是慢指针两倍,所得慢指针当前路径为n倍环长度。
继续:
从此点开始,用两指针分别从头和快慢指针相遇节点开始走,相遇的节点即为入环节点。
也即s1=0,s2=n*b,那么走非环路径a后即有,s1=a,s2=a+n*b,两者相遇在入环节点。
code:
struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {} }; class Solution { public: ListNode *detectCycle(ListNode *head) { ListNode *p = head, *q = head; while (p != nullptr) { q = q->next; if (p->next == nullptr) return nullptr; p = p->next->next; if (p == q) { //重新走一遍 p = head; while (p != q) { p = p->next; q = q->next; } return p; } } return nullptr; } };
【Over】

浙公网安备 33010602011771号