问题
例子
思路
- 方法1 O(n) O(n)
用map存储结点 - 方法2 O(n) O(1)
- 方法3 O(n) O(1)
快慢指针,找到相遇结点后,将问题变成->找到两个单链表相交的起始节点问题
代码
//方法1
public class Solution {
public ListNode detectCycle(ListNode head) {
Map<ListNode,Integer> map = new HashMap<>();
while(head!=null){
if(map.containsKey(head))
return head;
else{
map.put(head,1);
head = head.next;
}
}
return null;
}
}
//方法2.1
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null) return null;
ListNode slow=head,fast=head.next;//走了一次
//fast跑的快,只看它就好了
while(fast!=null && fast.next!=null) {
if(fast==slow) break;
else{
fast =fast.next.next;
slow=slow.next;
}
}
//找到了
if(fast!=null && fast.next!=null) {
fast=fast.next;//第一个结点是相遇点的下一个结点
while(head!=fast)
{
head=head.next;
fast=fast.next;
}
return head;
}
return null;
}
}
//方法2.2
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode res = get(head);
if(res==null) return null;
else{
ListNode l1=head;
ListNode l2=res.next;
while(l1!=l2){
l1=l1.next;
l2=l2.next;
}
return l1;
}
}
public ListNode get(ListNode head) {
if(head==null ||head.next==null) return null;
ListNode slow=head,fast=head.next;
while(fast!=null && fast.next!=null) {
if(fast==slow) return slow;
else{
fast=fast.next.next;
slow=slow.next;
}
}
return null;
}
//方法3
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null || head.next==null) return null;
//是否有环
ListNode fast=head.next;
ListNode slow = head;
while(fast!=null && fast.next!=null){
//有环
if(fast==slow){
ListNode temp = fast.next;
fast.next=null;//把环打开,变成相交链表问题
return getIntersectionNode(head,temp);
}
fast = fast.next.next;
slow = slow.next;
}
//没有环
return null;
}
public ListNode getIntersectionNode(ListNode h1, ListNode h2){
ListNode a = h1;
ListNode b = h2;
while(h1!=h2){
h1 = h1==null?b:h1.next;
h2 = h2==null?a:h2.next;
}
//相交点或null(不相交)
return h1;
}
}