题目描述:
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
Level | AC rate |
Medium | 56.4% |
题目解析(哈希表存储):
使用哈希表将我们经过的结点存储起来,直到出现了第一个重复结点时,则该结点为入环的第一个节点。代码如下:
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null)return null;
HashMap<ListNode,Integer> map = new HashMap<ListNode,Integer>();
while(head.next!=null){
if(map.containsKey(head))return head;
map.put(head,0);
head = head.next;
}
return null;
}
}
执行用时:3 ms, 在所有 Java 提交中击败了20.54%的用户
内存消耗:41.9 MB, 在所有 Java 提交中击败了45.28%的用户
题目解析(快慢指针):
快慢指针的原理就不介绍了,详细可以看:
使用快慢指针,这里涉及到了数学计算的问题,比如从头结点到入环的第一个结点需要走A步,绕环一圈需要走B步,假设目前快慢指针于X处相遇,相遇位置距入环结点需要走X步,那么也就是说此时快指针走了A+BN+X步,此时慢指针走了A+X步,快指针所走的距离应该是慢指针的两倍,也就是A+BN+X=2A+2X,即X=BN-A。这时将快指针的速度设为1,将慢指针放到头结点速度不变,慢指针到入环处需要走A步,而快指针需要走B-X=A-B(N-1)步。所以二者会在入环处相,代码如下:
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null)return null;
ListNode slow = head;
ListNode quick = head;
while(quick.next!=null&&quick.next.next!=null){
slow = slow.next;
quick = quick.next.next;
if(slow==quick){
slow = head;
while(slow!=quick){
slow = slow.next;
quick = quick.next;
}
return slow;
}
}
return null;
}
}
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:41.6 MB, 在所有 Java 提交中击败了80.87%的用户