141. 环形链表

83 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

141. 环形链表

力扣题目链接

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

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

示例1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

提示:

  • 链表中节点的数目范围是 [0, 104]
  • 105 <= Node.val <= 105
  • pos 为 1 或者链表中的一个 有效索引 。

进阶: 你能用 O(1)(即,常量)内存解决此问题吗?

思路:

判断链表有环的问题,可以采用快慢指针的方法来解决。我们规定快指针每次移动两步,慢指针每次移动一步,如果链表有环,那么两个指针终将相遇,此时返回true。如果链表没环,当快指针走到链表末尾时,直接返回false

因为只需要维护两个指针变量,因此空间复杂度是O(1)

下面是完整代码:

快慢指针

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */

/**
 * @param {ListNode} head
 * @return {boolean}
 */
var hasCycle = function(head) {
    if (!head || !head.next) return false;
    let fast = head.next.next;
    let slow = head.next;
    while(fast !== slow) {
        if (!fast || !fast.next) return false;
        fast = fast.next.next;
        slow = slow.next;
    }
    return true;
};

时间复杂度:O(n)

空间复杂度:O(1)

投机取巧

本题还可以采用JSON的一个特性求解,就是如果对象中存在循环引用,那么执行JSON.stringify() 会报错。我们可以通过是否可以捕获到错误来判断是否有环。代码如下:

/**
 * @param {ListNode} head
 * @return {boolean}
 */
var hasCycle = function(head) {
    let flag = false;
    try {
        JSON.stringify(head);
    } catch {
        flag = true;
    }
    return flag;
};

当然在平常的面试或者工作中,不要使用此方法来求解。

总结

本题考查快慢指针的应用,难度系数简单。需要注意的是,要处理边界情况,防止获取undefinednext属性,从而导致报错。