面试题22:链表中环的入口节点(Java版)

题目:如果一个链表中包含环,那么应该如何找出环的入口节 点?从链表的头节点开始顺着next指针方向进入环的第1个节点为环的入口节点。例如,在如图4.3所示的链表中,环的入口节点是节点 3。

题目分析

因为要找到环的入口节点,所以首先需要判断链表是否有环,当链表有
环时,我们可以使用两个指针(一个快指针和一个慢指针),快指针一
次移动两下,慢指针一次移动一下,当两个指针相遇时则表明此时两个
指针已经进入到环里了,且设快指针移动了2k步,则慢指针移动了k步,
仔细观察可以发现当慢指针再移动k步会回到原地(因为2k步的位置和
k步相同),即移动k步相当于移动了整数圈环(所以k为环中节点的整
数倍)。所以我们可以将一个指针p2指向那个移动了k步的慢指针再将
一个指针p1指向链表的表头,两个指针再同时移动,当p1移动到环的
入口时,因为指针p2始终比指针p1快k步,又因为k为环中节点的整数
倍,所以指针p2也指向了环的入口节点即当p1与p2相遇的时候,指向
的节点就为环的入口节点。

实际实现

// 获取链表中两个快慢指针相遇的位置,
// 即两个指针在环中相遇的位置
private ListNode getNodeInLoop(ListNode head) {
    // 当节点少于两个时无法形成环,所以返回null
    if (head == null || head.next == null) {
        return null;
    }
    // 初始化快指针和慢指针的位置
    ListNode slow = head.next;
    ListNode fast = slow.next;
    // 当快指针不为null时,则同时移动快慢指针
    // (快指针移动两格,慢指针移动一格)
    // 如果循环过程中出现fast为null的话则
    // 证明链表中不存在环返回null
    while (fast != null) {
        // 如果slow和fast相等,返回
        // 两个指针相遇的位置
        if (slow == fast) {
            return slow;
        }
        slow = slow.next;
        fast = fast.next;
        if (fast != null) {
            fast = fast.next;
        }
    }
    return null;
}

public ListNode detectCycle(ListNode head) {
    ListNode inLoop = getNodeInLoop(head);
    // 如果链表中不存在环则返回null
    if (inLoop == null) {
        return null;
    }

    // 初始化node为头结点
    ListNode node = head;
    // 当node != inLoop时node和inLoop同时移动
    // 当node与inLoop相等时说明已经到环的入口点了
    while (node != inLoop) {
        node = node.next;
        inLoop = inLoop.next;
    }
    return node;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值