【LeetCode】Linked List Cycle

题目连接:环形链表II

题目描述:返回链表开始入环的第一个节点,如果无环,则返回null。
方法一、哈希表
HashSet存储链表节点,遍历链表,当一个节点在哈希表中已存在时,说明链表有环,且该节点就是入环的第一个节点。
该方法用于判断链表是否有环,和链表入环第一个节点,思路一模一样。
时间复杂度O(n),空间复杂度O(n)。
代码如下:

public static ListNode detectCycle(ListNode head) {
        Set<ListNode> set=new HashSet<>();
        while (head!=null){
            if(set.contains(head))
                return head;
            set.add(head);
            head=head.next;
        }
        return null;
    }

方法二:快慢指针 两次相遇
双指针第一次相遇:
慢指针slow每次移动一个节点,快指针fast每次移动两个节点,如果链表无环,那么一定是fast先到达终点,即为null。
如果链表有环,那么slow和fast一定会在环内相遇,即fast == slow。而且相遇时,fast一定比slow多走了n个环的长度。(入环之后,两个指针就一直在环内绕圈。)
设从起点到入环点的节点长度为a,环内节点的长度为b,相遇时slow走过的长度为s,fast走过的长度为f,因为fast每步走两个节点,slow每步走一个节点,那么一定有f=2s。又因为相遇时fast比slow多走了n个环的长度,所以有f-s=nb。
解得s=nb,f=2nb。即相遇时,fast和slow分别走了2n、n个环的周长,总步长为2nb,nb。
双指针第二次相遇:
已知若一个指针从链表起点出发,每次走到入环点时,走过的长度为k=a+nb。慢指针slow从起点出发到相遇点,已走过nb步,那么再走步长a就能到达入环点。
a为起点到入环点的长度,是未知的。但是从起点走步长a也能到达入环点。
此时让一个指针third从起点出发,slow从fast和slow的相遇点出发,以相同的速度,当两者相遇,即third ==slow时,就都走过步长a,刚好到达入环点。(一个从环外出发,一个在环内转圈,两者能够相遇一定是在环内。third从起点出发到入环点走过a步,slow再走a步同样到达入环点。所以相遇就是在入环点)

时间复杂度O(n),空间复杂度O(1)。

代码如下:

	public static ListNode detectCycle(ListNode head){
        if(head==null)
            return null;
        ListNode slow=head,fast=head;
        while (fast!=null){
            slow=slow.next;
            if(fast.next==null)
                return null;
            fast=fast.next.next;
//            相遇,说明成环,
            if(fast==slow){
            //从起点出发
                fast=head;
                while (fast!=slow){
                    fast=fast.next;
                    slow=slow.next;
                }
                return slow;
            }
        }
        return null;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值