剑指Offer-55.链表中环的入口结点(C++/Java)
题目:
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
分析:
利用快慢指针,如果链表中存在环的话,则快指针一定在环中的某个节点与慢指针相遇。
设头节点到链表的环的入口结点的结点个数为p,入口结点到两指针相遇结点的结点个数为a,相遇结点到入口结点的结点个数为b。
快指针每次走两个结点,慢指针每次走一个结点,到两指针相遇之时,访问的结点个数是两倍的关系,那么根据上面的条件我们知道。
2*(p+a) = p + a + b + a => p = b
也就是头结点到入口结点的结点数等于相遇结点到入口结点的结点个数,根据这个条件我们可以快速的求解此问题。
程序:
C++
class Solution { public: ListNode* EntryNodeOfLoop(ListNode* pHead) { if(pHead == nullptr) return nullptr; ListNode* fast = pHead; ListNode* slow = pHead; ListNode* pos = nullptr; while(fast && slow){ fast = fast->next; slow = slow->next; if(fast){ fast = fast->next; } else return nullptr; if(fast == slow){ pos = slow; break; } } ListNode* start = pHead; if(pos != nullptr){ while(pos && start){ if(pos == start) return start; pos = pos->next; start = start->next; } } else{ return nullptr; } } };
Java
public class Solution { public ListNode EntryNodeOfLoop(ListNode pHead) { if(pHead == null) return null; ListNode fast = pHead; ListNode slow = pHead; ListNode pos = null; while(fast != null && slow != null){ fast = fast.next; slow = slow.next; if(fast != null) fast = fast.next; else{ return null; } if(fast == slow){ pos = slow; break; } } ListNode start = pHead; if(pos != null){ while(start != pos){ pos = pos.next; start = start.next; } return pos; } return null; } }