[Leetcode] 141. Circular Linked List

topic

leetcode 141. Circular linked list

Insert picture description here
Insert picture description here

answer

The method parameter given by leetcode is only ListNode. At first, I couldn't figure out how to receive this pos? ?

Idea 1 : Use a hash table to let each node be the key and value to record the number of occurrences of each node. If a node appears twice, it means there is a ring.

Either HashMap or HasnSet can be used here.

    /**
     * 每次把哈希表中没有的结点添加到哈希表中。
     * 如果是环,那么在尾结点的下一个结点肯定在哈希表中,此时就可以说明有环。
     * 如果不是环,那么在尾结点的下一个结点就是null,此时结束循环,说明不是环
     * @param head
     * @return
     */
    public boolean hasCycle(ListNode head) {
    
    
        Set<ListNode> set = new HashSet<>();
        while(head != null) {
    
    
            if(set.contains(head)) {
    
    
                // 说明存在环
                return true;
            } else {
    
    
                set.add(head);
            }

            head = head.next;
        }
        return false;
    }

the complexity:

  • Time complexity: traverse N times, so it is O(N).
  • Space complexity: Use a hash table to store up to N nodes, so it is O(N).

Idea 2 : Use dual pointers, one is slow pointer, moving one node at a time, and the other is fast pointer, moving two nodes at a time.

For fast and slow pointers, a problem needs to be solved. For example, if a singly linked list uses fast and slow pointers to traverse from left to right, the fast pointer must first encounter null. So is it: fast.next.next == null? In fact, there is no need, just: fast.next == null. But only this is wrong, the speed pointer has to consider the parity of the number of nodes . For odd numbers, this is fine, but for even numbers, there is a problem. A null pointer exception will occur. You can draw a picture. The fast pointer will jump to null at the end. You might say that jumping to null does not just end? Yes, but it is over after another round of judgment is over. The problem is that the last time it is judged, the null pointer calls next. So we have to judge: fast == null.

Summary (master): For fast and slow pointers, the parity problem of the number of nodes needs to be solved. Because the fast pointer reaches the end first, the fast pointer needs two conditions to judge whether it is over: if the current fast pointer is empty or the next fast pointer The node is empty, indicating the end .

  • Assuming that it is acyclic, then null is encountered, and the fast pointer must be encountered first.
  • Assuming that there is a loop, then null will not be encountered, but the fast and slow pointers will continue to loop? Look at the picture below:

Insert picture description here

Through the above figure, it is found that if the linked list is a ring, then the fast and slow pointers must be able to meet if they keep circulating . (I won't prove it...)

Code:

    /**
     * 
     * @param head
     * @return
     */
    public boolean hasCycle2(ListNode head) {
    
    
        ListNode fast = head;
        ListNode slow = head;
        // 如果不是环,结点个数影响快指针跳的位置,所以需要写一个处理奇偶情况。此题跟求链表的中间结点那道的条件一样。不过不需要去考虑中间结点有2个的问题
        while(fast != null && fast.next != null) {
    
    
            // 必须先走,才判断是否为环
            // 慢指针走一步
            slow = slow.next;
            // 快指针走两步
            fast = fast.next.next;
            // 如果遇到环,则快指针和慢指针一定会在环相遇
            if(fast == slow) {
    
    
                return true;
            }
        }
        return false;
    }

Because this question is rather special, you can also do this:

    public boolean hasCycle(ListNode head) {
    
    
        if(head == null || head.next == null) {
    
    
            return false;
        }
        // 两种写法
        ListNode slow = head;
        ListNode fast = head.next;
        while(fast != slow) {
    
     
            if(fast == null || fast.next.next == null) {
    
    
                return false;
            }
            fast = fast.next.next;
            slow = slow.next;
        }

        return true;
    }

the complexity:

  • Time complexity: O(N)
  • Space complexity: just use two pointers, which can be regarded as O(1)

Guess you like

Origin blog.csdn.net/weixin_41800884/article/details/107775494