【每日算法】力扣141. 环形链表

88 阅读2分钟

「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战」。

描述

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

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

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

 

示例 1:

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



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



输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
 

提示:

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

做题

我刚开始做的时候,想着拿第一个节点为基准,一直遍历后面的节点,当节点等于第一个节点时,就说明有环,现在才知道原来这个环不是再从头开始的。

记录节点法

第一种做法:记录节点法,利用哈希表记录遍历过的节点,如果当前的节点存在哈希表中,就说明是有环的。

public boolean hasCycle(ListNode head) {
        //记录节点法
        Map<ListNode,ListNode> map =new HashMap();
        while(head!=null){
            ListNode node = map.get(head);
            if(node == null){
                //当该节点不存在时,存入map
                map.put(head,head);
            }else{
                //当节点存在,说明有环
                return true;
            }
            head=head.next;
        }
        return false;
    }
		

image.png

快慢指针法

第二种做法:快慢指针法,慢指针每次只走一步,快指针走两步,如果有环,那么快慢指针就会相遇。

例如,head = [3,2,0,-4], pos = 1

模拟快慢指针:

快:0 > 2 > -4 > 0 > 2 > -4

慢:2 > 0 > -4 > 2 > 0 > -4

六次就能相遇了,至于为啥会相遇,我也不知道,只能推测,在一个环里,两个指针无论在哪里,一个走两步,另一个走一步,肯定会相遇。

public boolean hasCycle(ListNode head) {
        //快慢指针法
        ListNode slowIndex=head;
        ListNode fastIndex=head;
        while( fastIndex!=null && fastIndex.next!=null){
            slowIndex = slowIndex.next;
            fastIndex = fastIndex.next.next;
            if(slowIndex == fastIndex){
                return true;
            }
        }
        return false;
    }

image.png

理论上第二种做法的内存消耗应该会比较小,这里可能是误差的原因。

最后

今天就到这里了。

这里是程序员徐小白,【每日算法】是我新开的一个专栏,在这里主要记录我学习算法的日常,也希望我能够坚持每日学习算法,不知道这样的文章风格您是否喜欢,不要吝啬您免费的赞,您的点赞、收藏以及评论都是我下班后坚持更文的动力。