力扣第141题-环形链表

130 阅读2分钟

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

前言

力扣第141题 环形链表 如下所示:

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

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

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

示例 1:

一、思路

题目的意思很明确,就是确定链表中是否存在环,也就是说某个节点指向会指向它前面的某个节点(之前遍历过的)。如下图所示:

image.png

通过上面的描述,很明显能够使用 哈希表 来判断下一个节点是否为之前遍历过的。如下一个节点为之前遍历过的,则表示该链表会形成环。总共分为以下两个步骤:

  1. 遍历链表,并将当前节点接入到哈希集合中
  2. 如果遍历过程中,当前节点节点已存在哈希集合中,则代表存在环

伪代码如下所示:

while (next != null){
            if (set.contains(next)) return true;
            set.add(next);
            next = next.next;
        }
        return false;

进阶中有一个要求:你能用 O(1)(即,常量)内存解决此问题吗?。这要如何做呢?

快慢指针

示例中的链表如下所示,绿色表示快的指针,蓝色表示慢的指针。且 每次快指针移动两个,慢指针移动一个

image.png

  1. 向前移动一次如下所示:

image.png

  1. 再向前移动一次

image.png

此时我们发现快慢指针相遇了,说明链表中有环。因为如果没环的话,跑得快和跑得慢的不可能相遇的。

二、实现

实现代码

此处的实验代码用的快慢指针

public boolean hasCycle(ListNode head) {
    if (head == null || head.next == null) {
        return false;
    }
    ListNode slow = head;
    ListNode fast = head.next;
    while (true) {
        if (fast == null || fast.next == null) {
            return false;
        }
        if (fast == slow)   // 相遇返回 T
            return true;
        slow = slow.next;
        fast = fast.next.next;
    }
}

测试代码

public static void main(String[] args) {
    ListNode l1 = new ListNode(3);
    ListNode l2 = new ListNode(2);
    ListNode l3 = new ListNode(0);
    ListNode l4 = new ListNode(4);
    l1.next = l2;
    l2.next = l3;
    l3.next = l4;
    l4.next = l2;
    boolean flag = new Number141().hasCycle(l1);
    System.out.println(flag);
}

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~