102.带环链表

描述

给定一个链表,判断它是否有环。

样例

给出 -21->10->4->5, tail connects to node index 1,返回 true

挑战

不要使用额外的空间

思路

  1. 使用O(n)的额外空间时,在遍历整个链表的过程中用一个hash表存储当前结点的引用,如果hash表中已经存在当前结点的引用return false,否则加入hash表,如果遍历完整个链表仍旧没发现重复值证明链表没环
  2. 定义两个指针,一个快一个慢,设定快的跑两步,慢的跑一步,如果有环则它们一定会相遇

两种思路时间复杂度都是O(n)

变形题目

题目有一种变体,就是判断两个链表有没有交集,将第一个链表的末指针和第二个链表的头指针连接到一起,若有交集则一定存在环

代码

/**
 * Definition for ListNode.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int val) {
 *         this.val = val;
 *         this.next = null;
 *     }
 * }
 */
  1. 哈希表法
public class Solution {
    /*
     * @param head: The first node of linked list.
     * @return: True if it has a cycle, or false
     */
    public boolean hasCycle(ListNode head) {
        Set nodesSeen = new HashSet<>();
        while (head != null) {
            if (nodesSeen.contains(head)) {
                return true;
            } else {
                nodesSeen.add(head);
            }
            head = head.next;
        }
        return false;
    }
}
  1. 快慢指针
public class Solution {
    /*
     * @param head: The first node of linked list.
     * @return: True if it has a cycle, or false
     */
    public boolean hasCycle(ListNode head) {
        if (head == null || head.next == null) {
            return false;
        }
        
        // 注意要让跑的快的在前面,不然没跑完一圈就追上了
        ListNode slow = head;
        // 如果 fast 也赋值为 head 则在第一个结点就会跳出 while 循环
        ListNode fast = head.next;
        while (slow != fast) {
            // 在没追上慢指针的情况下,遍历完了整个链表,证明没有环
            if (fast == null || fast.next == null) {
                return false;
            }
            fast = fast.next.next;
            slow = slow.next;
        }
        // slow == fast时证明有环
        return true;
    }
}

你可能感兴趣的:(102.带环链表)