题目
该系列文章题目和思路均参考自:《剑指Offer》- Page 139
解法
思路:解决这个问题的思路首先是如何确定一个链表中有环。这个问题,我们可以使用快慢指针的方法,两个指针初始化都在链表头节点,然后一个(slow)一次走一步,另一个(fast)一次走两步。如果两个指针能够在某个地方相遇,则说明链表中包含环。
在确定了链表中包含环之后,第二步是找到环的入口节点。在上述过程中遍历slow和fast相遇时,将slow重置到head节点处,然后同时移动slow和fast节点,这样,两个指针再次相遇时即为环的入口节点。
/**
* 思路1
* 使用快慢指针的思想
*/
public static boolean listHasLoop(ListNode head) {
ListNode slow = head;
ListNode fast = head;
if (fast == null)
return false;
while (fast != null && fast.getNext() != null) {
slow = slow.getNext();
fast = fast.getNext().getNext();
if (slow == fast) {
return true;
}
}
return !(fast == null || fast.getNext() == null);
}
/**
* 找到环的入口地址
* 思路:
* 在上述过程中遍历到slow和fast相遇时,将slow重置到head节点处,然后同时移动slow和fast节点,
* 再次相遇时即为环的入口地址
*
* @param head
* @return
*/
public static ListNode findLoopPort(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.getNext() != null) {
fast = fast.getNext().getNext();
slow = slow.getNext();
if (fast == slow)
break;
}
if (fast == null || fast.getNext() == null)
return null;
slow = head;
while (slow != fast) {
slow = slow.getNext();
fast = fast.getNext();
}
return slow;
}