链表中环的入口点

题目描述

链表中环的入口节点是指一个有环链表中,环的入口节点。给定一个链表,若其中包含环,则输出环的入口节点;否则输出null。

例如,在如下图所示的链表中,环的入口节点是3(注意,这里环的入口节点不是算链表的第3个节点)。

说明:

不允许修改给定的链表。

要求空间复杂度为O(1)。

解题思路

链表中环的入口节点可以通过 Floyd 算法来解决,具体步骤如下:

  1. 使用快慢指针法判断链表是否有环,如果有,快指针回到链表头部,然后快慢指针以相同的速度向前移动,当两个指针再次相遇时,该节点就是环的入口节点。
  2. 如何证明这个算法是正确的?假设链表的头部到环的入口节点的距离为a,环的入口节点到两个指针相遇点的距离为b,相遇点到环的入口节点的距离为c。同时,假设快指针速度为慢指针的两倍,即v{fast}=2v{slow},慢指针走过的距离为x。

当快指针第一次到达相遇点时,快指针走过的距离为 a + nb + x,慢指针走过的距离为 a + x,由于快指针走过的距离是慢指针的两倍,因此有2(a+x)=a+nb+x,化简得到 a=(n-1)b+c。

当快指针回到链表头部时,慢指针距离环的入口节点的距离为a,因此快慢指针分别从链表头部和相遇点开始移动,相遇的节点即为环的入口节点。

因此,这种方法可以在O(1)的空间复杂度下找到链表中环的入口节点。

具体代码展示

package org.zyf.javabasic.letcode.list.application;

import org.zyf.javabasic.letcode.list.base.ListNode;

/**
 * @author yanfengzhang
 * @description ​
 * 链表中环的入口节点是指一个有环链表中,环的入口节点。给定一个链表,若其中包含环,则输出环的入口节点;否则输出null。
 * 说明:
 * 不允许修改给定的链表。
 * 要求空间复杂度为O(1)。
 * @date 2023/4/5  23:45
 */
public class EnterNodeInCycleList {

    /**
     * 使用快慢指针法判断链表是否有环,
     * 如果有,快指针回到链表头部,然后快慢指针以相同的速度向前移动,
     * 当两个指针再次相遇时,该节点就是环的入口节点。
     * <p>
     * 该算法的时间复杂度为O(n),空间复杂度为O(1)。
     */
    public ListNode entryNodeOfLoop(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;

        /*1. 判断是否有环*/
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {
                break;
            }
        }
        if (fast == null || fast.next == null) {
            /*说明没有环*/
            return null;
        }

        /*2. 有环,找入口节点*/
        fast = head;
        while (fast != slow) {
            fast = fast.next;
            slow = slow.next;
        }
        return fast;
    }

    public static void main(String[] args) {
        ListNode head = new ListNode(1);
        head.next = new ListNode(2);
        head.next.next = new ListNode(3);
        head.next.next.next = new ListNode(4);
        head.next.next.next.next = new ListNode(5);
        head.next.next.next.next.next = new ListNode(6);
        head.next.next.next.next.next.next = head.next.next;

        ListNode entryNode = new EnterNodeInCycleList().entryNodeOfLoop(head);
        System.out.println(entryNode.val);
    }
}

from:链表中环的入口点

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值