141J. Linked List Cycle

https://leetcode.com/problems/linked-list-cycle/

最好的办法是用哈希表。其实都需要懂。

Method 1:龟兔赛跑

首先上来判断是否是空 ListNode 和没有 next. 然后建立 dummyhead/ Sentinel 核心是 双指针,一个一次挪一步,一个一次挪两步。 如果有循环的话,那么.next 和 .next.next 永远不会为空。 所以如果任意一个为 null,就应当终止循环。 如果两个指针指到同一个位置,那么就判断循环了。

!!!!!! 注意 !!!!!!! while 那里判断的时候 一定要先判断 p2!= null 再判断 p2.next != NULL 否则的话,如果 p2 是 null 的话,p2.next 就会报错! !!!!!!!!!!!!!! 另外 dummyhead 这里是冗余的。

public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == null || head.next == null){
            return false;
        }
        ListNode dummyhead = new ListNode(0);
        dummyhead.next = head;
        ListNode p1 = dummyhead;
        ListNode p2 = dummyhead;
        while( (p1 != null) &&(p2 != null) &&(p2.next!=null)){
            p1 = p1.next;
            p2 = p2.next.next;
            if(p1 == p2){
                return true;
            }
        }
        return false;
    }
}
public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == null) return false;
        ListNode dummyHead = new ListNode(-1);
        dummyHead.next = head;
        ListNode slow = dummyHead;
        ListNode fast = dummyHead;

        while( fast!=null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(slow == fast) return true;
        }
        return false;
    }
}

Method 2: Set

就是把所有的节点都无脑加到一个 HashSet 里面,然后出现重复就报错。 缺点是运行时间似乎不如上面的方法。但是复杂度也是 O(N).看来直接 移动指针还是很快的。

public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == null || head.next == null){
            return false;
        }
        Set<ListNode> set = new HashSet<>();
        ListNode p = head;
        while(p != null){
            if(set.contains(p)){
               return true;
            }
            set.add(p);
            p = p.next;
        }
        return false;
    }
}

Last updated

Was this helpful?