前言
最近为什么突然开始刷题了呢。主要是这几年来一直有刷题的计划,但都不能很好的坚持下来。原因还是找不到正确的刷题方法,盲目刷题,一道题目可以想半天。于是我就放低自己的标准,每天刷一道题目,刷题时结合题解,一天也不会花太多时间。循序渐进,也不要有很大的功利性。
正文
今天分享一下刷到的比较有意思的题目,环形链表,题目大概就是要求找出环形链表的入口。
看题解的数学分析时,觉得有点意思,当然,我是想不到这种解决方案的。
主要使用快慢指针法,由于是环形链表,快指针肯定会和慢指针相遇。
那么通过推导可以得到以下公式:头节点到环形链表入口=在相遇节点到环形链表入口(可能会跑n圈)
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
// fast走两步,slow走一步
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
// 有环
// 在交点设置index1,头节点设置index2,同时出发,每次走一个节点,相交则为入口
// 假设a为头节点到环入口的距离,b为环入口到交点的距离,c环的长度,n为fast跑了多少圈
// slow跑了a+b,因为fast速度是slow的两倍,fast跑了2(a+b)
// 那么2(a+b)=a+b+nc,则a+b=nc
// a=nc-b,翻译过来就是 我从起点跑到环入口=我从交点开始,跑了n圈后,回到了环入口。
ListNode node1 = fast;
ListNode node2 = head;
while (node1 != node2) {
node1 = node1.next;
node2 = node2.next;
}
return node1;
}
}
return null;
}