题目
一个链表中包含环,请找出该链表的环的入口结点
个人思路分析
一定要保证思维有序,分析问题后即使最后没有得到最完美的答案,至少方向正确不能跑偏。
- 链表结构
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
根据题目中对链表的定义 ==> 环必不可能出现在链表中部
环特点/性质
首尾相连,末尾节点next引用指向链表头 ==> 基本确定需要两个指针,检测指针相遇情况核心问题
1. 若链表带环,遍历终止条件难以确定
2. 环长度不明,标记入口难度大
offer巧妙解法
- 在基本思考的基础上,采用快慢指针标记环入口
- 结合追击问题特点,快第一次追上慢一定比慢多走了一圈环长
- 所以将快慢相遇作为遍历终止条件,并得到环长
- 灵活转换成查找链表中倒数第k个节点问题
- 注意细节:计数问题 ==> 倒数k,快指针应该先走几步
MyCode
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
if (pHead == null || pHead.next == null)
return null;
if (pHead.next.next == null)
return pHead;
ListNode pfast = pHead, pslow = pHead;
int fastCounter = 0, slowCounter = 0;
while (true) {
pfast = pfast.next.next;
pslow = pslow.next;
fastCounter += 2;
slowCounter++;
if (pfast == pslow)
break;
}
// one loop faster
int loopLength = fastCounter - slowCounter;
pfast = pHead;
pslow = pHead;
for (int i = 1; i <= loopLength; i++) {
pfast = pfast.next;
}
while (pfast != pslow) {
pfast = pfast.next;
pslow = pslow.next;
}
if (pfast == pslow)
return pslow;
return null;
}
}