环形链表II
这个题有两种解法:
1.哈希表法
最简单也最容易想到的就是哈希表法,每次扫描将节点存入表中并且判断当前节点是否存在于表中,当第二次存入的时候返回当前节点。
//leetcode-142
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode current = head;
Set<ListNode> set = new HashSet<>();
while(current != null){
if(set.contains(current)){
return current;
}
else{
set.add(current);
current = current.next;
}
}
return null;
}
}
2.双指针法
双指针法需要结合一些数学知识,定义两个快慢指针,慢指针每次走一步,快指针每次走两步,这样相当于快指针每次追赶慢指针一步,所以二者总会相遇。当相遇的时候我们可以发现慢指针走了n个环的长度(数学证明网上有很多,在此不做赘述),因为要想走到环的入口要走的长度应该为环外的长度+环长度的整数倍,因为此时慢指针已经走了n个环的长度,所以只要再走一个环外的长度就可以走到环的入口,我们现在需要一个指针同样再走一个环外的长度就可以到环的入口,所以此时将快指针重新指向头结点,然后让快慢指针同时移动,当二者相等时其指向的位置就是环的入口。
//leetcode-142
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while(true){
if(fast == null || fast.next == null) {
return null;
}
slow = slow.next;
fast = fast.next.next;
if(slow == fast){
break;
}
}
fast = head;
while(fast != slow){
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
未完待续。。。