链表中环的入口节点

  

题目描述

对于一个给定的链表,返回环的入口节点,如果没有环,返回null
拓展:
你能给出不利用额外空间的解法么?
 
 
 

 牛客上的一个题目,判断是否有环,使用快慢指针即可,要找到环的入口就需要再分析一下

方法一:

因为快指针的速度是慢指针的2倍,所以当快慢指针第一次相遇时,快指针走过的路程(暂时就这么叫)是慢指针的2倍

所以可以得出如下等式:假设快慢指针相遇时,快指针已经绕了n圈

2(x+y)=x+y+n*(y+z)

整理一下可得

x=(n-1)(y+z)+z

可以发现y+z恰好是环的一圈,x等于n-1圈环加z,所以第一次相遇后慢指针回到起点,快慢指针以相同的速度向前走(一次走一格),

当慢指针走了x长的路程时,快指针绕了n-1圈并且还走了z,这时他们恰好相遇在入口(真巧)

 1 /**
 2  * Definition for singly-linked list.
 3  * class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode(int x) {
 7  *         val = x;
 8  *         next = null;
 9  *     }
10  * }
11  */
12 public class Solution {
13     public ListNode detectCycle(ListNode head) {
14         if(head == null){
15             return null;
16         }
17         ListNode slow = head;
18         ListNode fast = head;
19         while(fast != null && fast.next != null){
20             fast = fast.next.next;
21             slow = slow.next;
22             if(fast == slow){
23                 break;
24             }
25         }
26         if(fast == null || fast.next == null){
27             return null;
28         }
29         slow = head;
30         while(slow != fast){
31             slow = slow.next;
32             fast = fast.next;
33         }
34         return slow;
35     }
36 }

方法二(可先看代码):

 

 

 

 1 /**
 2  * Definition for singly-linked list.
 3  * class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode(int x) {
 7  *         val = x;
 8  *         next = null;
 9  *     }
10  * }
11  */
12 public class Solution {
13     public ListNode detectCycle(ListNode head) {
14         if(head == null || head.next == null){
15             return null;
16         }
17         ListNode slow = head,fast = head.next;
18         ListNode t = head.next;
19         while(slow != fast){
20             if(fast == null || fast.next == null){
21                 return null;
22             }
23             slow = slow.next;
24             fast = fast.next.next;
25             if(slow == fast)//这里必须加判断,否则会出现空指针异常
26             t = fast.next;
27         }
28         
29         slow = head;
30         while(slow != t ){
31             slow = slow.next;
32             t = t.next;
33         }
34         return slow;
35     }
36 }

方法二是看了leetcode141的题解才有的想法,但是没有方法一,直接方法二就有点困难。我觉得方法二有点鸡肋

posted @ 2020-09-07 11:41  雨下_整夜  阅读(238)  评论(0)    收藏  举报