leetcode刷题之环形链表

本文介绍了两种方法解决LeetCode问题142——环形链表II:一种是利用哈希集合存储已访问节点,另一种是通过快慢指针策略找出链表首入环节点。讲解了两种方法的时间复杂度、空间复杂度,并通过反证法验证了快慢指针法的正确性。
摘要由CSDN通过智能技术生成

142. 环形链表 II - 力扣(LeetCode)
题目:给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

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

不允许修改 链表。
在这里插入图片描述

方法一哈希方法

public ListNode detectCycle1(ListNode head) {
    HashSet<ListNode> hashSet=new HashSet<>();  //用来存储访问过的结点
    ListNode listNode=head;
    while(listNode!=null){
        if(hashSet.contains(listNode)){
            return listNode;    //回到访问过的结点,即入环位置
        }else{
            hashSet.add(listNode);
            listNode=listNode.next;
        }
    }
    return null;
}
  • 时间复杂度:O(N),其中 N为链表中节点的数目。我们恰好需要访问链表中的每一个节点。
  • 空间复杂度:O(N),需要将每个结点都存储在HashSet中。

方法二快慢指针——我吹过你去时的风,而又在原点相遇

设置两个指针,快指针每次前进两步,慢指针每次前进一步

fig1

首先有一个结论:慢指针必然在走完循环一圈之内与快指针相遇

假设在进入循环b步之后与快指针相遇,则slow前进a+b

fast前进a+n*(b+c)+b

此时的路程fast=2*slow(由速度决定)

则有等式a+n*(b+c)+b=2*(a+b)

可以解得a=(n-1)b+n*c

此时再加一个指针ptr指向head,与slow指针的速度相同,同时向前移动,则两者会在入环点相遇

ptr前进a,slow同样也前进a

此时slow=a+b+a=a+b+(n-1)b+n*c=a+n(b+c)

此时ptr和slow的位置都在入环点,即ptr和slow相遇位置即为入环点

    public ListNode detectCycle(ListNode head) {
        if(head==null) return null;
        ListNode fast=head;
        ListNode slow=head;
        while(fast!=null){
            slow=slow.next;
            if(fast.next!=null){
                fast=fast.next.next;
            }else{
                return null;  //如果存在环,必然可以一直访问下去,不会遇到null
            }
            if(fast==slow){           //快慢指针相遇
                ListNode ptr=head;
                while(ptr!=slow){     //判断ptr和slow是否相遇,有可能在原点相遇
                    ptr=ptr.next;
                    slow=slow.next;
                }
                return ptr;
            }
        }
        return null;
    }

最后利用反证法证明一个前面的结论

假设慢指针在进入循环一圈之后与快指针相遇

此时slow的路程为slow=a+n*(b+c)+b (n>=1)

fast的路程为fast=2*slow

则路程差distance=fast-slow=slow=a+n*(b+c)+b

如果这是她们第一次相遇,则路程差必为b+c

而distance明显大于b+c,说明并不是第一次相遇,与假设相矛盾,故假设不成立。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图灵的喵酱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值