1. 链表中有环:
快慢指针,一个每次两步,一个一步,最后相遇,就一定有环。
public boolean hasCycle(ListNode head) {
if (head == null) return false;
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (fast == slow) {
return true;
}
}
return false;
}
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) return false;
ListNode slow = head;
ListNode fast = head.next;
while (slow != fast) {
if (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
else {
return false;
}
}
return true;
}
2. 找到环的入口(剑指55)
1) 两个指针,一个从链表头开始,另一个从相遇点开始,每次都走一步,最后一定在环入口相遇。
public ListNode EntryNodeOfLoop(ListNode pHead)
{
if (pHead == null || pHead.next == null || pHead.next.next == null) {
return null;
}
ListNode fast = pHead.next.next;
ListNode slow = pHead.next;
// 判断有没有环
while (fast != slow) {
if (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
else {
return null;
}
}
// 此时fast==slow,就是相遇点
fast = pHead;
while (fast != slow) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
2)如果链表中环 有n个结点,指针P1在链表上向前移动n步,然后两个指针以相同的速度向前移动。当第二个指针指向环的入口结点时,第一个指针已经围绕着环走了一圈又回到了入口结点。
重点就是:如何找到环的长度
public ListNode EntryNodeOfLoop(ListNode pHead)
{
if (pHead == null || pHead.next == null || pHead.next.next == null) {
return null;
}
ListNode fast = pHead.next.next;
ListNode slow = pHead.next;
while (fast != slow) {
if (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
else {
return null;
}
}
// 环的长度
int loopLen = 1;
while (slow.next != fast) {
slow = slow.next;
loopLen++;
}
fast = slow = pHead;
int i = 0;
while (i < loopLen) {
fast = fast.next;
i++;
}
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}