141 环形链表

一、题目

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false

二、题解

思路: 快慢指针(龟兔赛跑)。

  • 慢指针 slow 每次走 1 步,快指针 fast 每次走 2 步。
  • 如果链表无环,fast 会先到达 null(链表尾部),返回 false
  • 如果链表有环,fast 终会在环内追上 slow(两者相遇),返回 true
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */

public class Solution {
    public boolean hasCycle(ListNode head) {

        // 【边界情况】如果链表为空,或者只有一个节点,根本构不成环,直接返回 false
        if(head == null || head.next == null) {
            return false;
        }

        // 【初始化快慢指针】
        // 慢指针 slow 起点在 head,快指针 fast 起点在 head.next。
        // (让 fast 先走一步,是为了能顺利进入下面的 while 循环条件判断)
        ListNode slow = head, fast = head.next;

        // 【核心循环】只要两个指针没相遇,就一直跑
        while(slow != fast){
            // 如果快指针走到了尽头(遇到 null),说明链表是有尾巴的,绝对没有环
            if(fast == null || fast.next == null) {
                return false;
            }
            // 慢指针每次走 1 步
            slow = slow.next;
            // 快指针每次走 2 步
            fast = fast.next.next;
        }

        // 如果能跳出 while 循环,说明 slow 和 fast 相遇了!必定有环
        return true;
    }
}

时间复杂度O(n)O(n)

空间复杂度O(1)O(1)

评论