判断给出的单链表是否是一个循环的链表,如果是一个循环的单链表的话,输出循环开始的节点
最简单的做法,对整个单链表进行hash,但是要占用o(n)的空间复杂度,
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode node = head;
Integer t ;
//ListNode end = new ListNode(-1);
HashMap<ListNode, Integer> map = new HashMap<>();
while(node != null){
t = map.get(node);
if(t == null){
map.put(node, node.val);
}
else {
return node;
}
node = node.next;
}
return null;
}
}
题目要求不使用额外的辅助空间,通过查询discuss;
通过控制双指针进行操作,一个指针的步长为1,另外一个指针的步长为2,
如果存在循环圈,步长为2的指针肯定会跟步长1的指针走到同一个node上面;
此时,我们定义x表示从头指针head到开始循环节点的长度,定义y为循环链表的长度
如果链表存在环,假设步长1指针和步长2指针在循环圈内的第m个node重叠
那么步长1指针走了有 x + ty + m步
步长2指针走了x + ky + m步
因为 步长2 = 2倍的步长1
所以可以知道 2(x + ty + m)= x + ky + m
故(k-t)y = x + m; 在循环圈内走多x步就可以到达开始循环的头结点了!get it
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode node1 = head;
ListNode node2 = head;
do{
if(node1 == null || node2 == null){
return null;
}
node1 = node1.next;
node2 = node2.next;
if(node2 == null){
return null;
}
node2 = node2.next;
}while(node1 != node2);
node1 = head;
while(node1 != node2){
node1 = node1.next;
node2 = node2.next;
}
return node1;
}
}