题目: 给定一个链表,如果它是有环链表,实现一个算法返回环路的开头节点。
有环链表的定义:在链表中某个节点的next元素指向在它前面出现过的节点,则表明该链表存在环路。
示例:
进阶:
你是否可以不用额外空间解决此题?
方法:快慢指针
思路:
数学证明,快慢指针
1.设置环路的开头节点为成环节点,从头节点到成环节点的路程为a,成环节点循环路程一圈为b
2.使用快慢指针,因为快指针每次都多走一步,如果成环他们一定可以相遇,如果不成环当前快指针会为空
3.快慢指针第一次相遇时,快指针路程f=2s (n为圈数) 慢指针路程s 快指针一定比慢指针多走n圈
4.所以 f=2s=s+nb => s=nb 所以慢指针走的路程为nb
5.设置k=a+nb为到成环节点的路程 (路程为a,a+b,a+2b,a+3b…a+nb时都是成环节点)
6.所以快慢指针第一次相遇时,慢指针离成环节点的距离为a
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
/**
* 执行用时:0 ms, 在所有 Java 提交中击败了100.00% 的用户
* 内存消耗:37.9 MB, 在所有 Java 提交中击败了99.94% 的用户
* @param head
* @return
*/
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = slow;
while(true){
//快指针能走完 无环
if(fast==null || fast.next==null){
return null;
}
fast = fast.next.next;
slow = slow.next;
//相遇退出
if(fast==slow){
break;
}
}
//还要走a举例到达成环节点
fast = head;
while(fast!=slow){
fast=fast.next;
slow=slow.next;
}
return fast;
}
}