本次写的题目是环形链表Ⅱ,为LeetCode里面的题目,让我们来康康是如何解出这道题目的吧,各位尚没有思路的小伙伴可以跟随着博主的解题思路一步步来,感受一下😎
🌱分析阶段
在本题中,要解决问题,首先要先想明白:如果已知有一个链表,而我们要判断其是否成环,那么要怎么判断呢?
这个问题解决要用到的技巧就是快慢结点,本类的问题归根就是追击问题,如果成了环,那么快结点两步两步走,慢结点一步一步走,若有环,都在同一个圈内,那么总能追上。
拓展🧐:那么如果说我们想要快一点,可不可以将快结点设置三步三步走,甚至说是多几步这样子走呢?
答案是不行的~例如我们要快结点三步三步走,那么很可能会一直错过相遇喔😫
在明白了追击问题后,我们可以得出总结:追击问题中最快且最稳定的方法是快结点路程为慢结点路程的两倍✨
之后为了弄明白要怎样获得成环的最初位置,我们设置下面几个参数:L—从链表头结点到成环最初结点位置 C—环的长度 Y—快慢两结点相遇位置到成环最初结点位置(从顺时针看)
我们都知道快结点走过的路程是慢结点的两倍,由此我们可以得出 2*slow = fast 这样的抽象公式(用于之后演算)
先假如慢结点进入的第一圈就和快结点遇到了,那么可以推算出下面的结论👇:
那么如果慢结点是在快结点转很多圈后慢结点才进入环的呢?还会有这样的规律出现么?下面请看博主再次演算的过程👇:
那么我们知道了 头结点到最初成环位置的距离 = 两结点相遇位置到最初成环位置的距离 这个规律有什么用处呢?在这里博主先卖个关子,浅画一个图,看看有没有小伙伴能get到什么😎
由此图,我们已经有fast结点出现,在slow和fast相遇后fast在相遇的位置上,那么如果此时我们将slow放回链表最初位置,然后fast和slow链表都同时一步一步走,那么最后,两个结点的相遇就会为最初的成环位置上了😎✨✨✨
📢总结:要完成本题,大致思路十分简单:①制造快慢结点相遇;②相遇后将慢结点放回链表头结点位置,与快结点同时一步步走,相遇处即为成环位置;但是其中的推测过程值得我们反复思考。
🌱代码阶段
在知道大致思路以后写代码是相对于较容易的事情,但是在知道大致思路后,正式写代码前,我们要先考虑有无特殊情况出现,但由于这题的代码过于简单,只是分析问题的过程比较复杂,所以没有什么需要特殊考虑的。具体的细节请看下面代码~👇
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null) return null;
ListNode fast = head;
ListNode slow = head;
//判断有无成环并让快慢结点相遇
while(fast!=null&&fast.next!=null){
fast= fast.next.next;
slow = slow.next;
if(fast==slow) break;
}
//在退出上面循环后,有可能是因为没有成环链表而导致退出的
//下面判断是不是因为没有成环链表才退出的循环
if(fast==null||fast.next==null){
return null;
}
//判断有成环链表后,继续最后一步,寻找成环处
slow = head;
while(slow!=fast){
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
至此,全部的代码就写完了,让我们运行逝逝吧~
nice😎✨✨
制作本篇文章实在不易,要是有帮助到您的话请不要厉色点赞哦🥺你的每一个点赞评论都是对博主莫大的鼓励🥺🥺