23_剑指offer_java版本_链表中环的入口点

目录

 

题目描述

测试用例

题目考点

解题思路

自己解题

参考解题


题目描述

如果一个链表中包含环,如何找出环的入口节点?例如,在如下图所示的链表中,环的入口节点是节点3。

 

测试用例

  • 功能测试(链表中包含或者不包含环;链表中有多个或者只有一个节点)
  • 特殊输入测试(链表头节点为空指针)

题目考点

  • 考察应聘者对链表的理解。
  • 考察应聘者所写代码的鲁棒性(考虑的全面性)。
  • 考察应聘者分析问题的能力。把一个问题分解成多个简单的步骤,是一种常用的解决复杂问题的方法。

解题思路

  1. 确定一个链表中包含环

用两个指向头节点指针,同时从链表的头节点触发,一个指针一次走一步,另一个指针一次走两步。如果走得快的指针追上了走得慢的指针,那么链表就包含环,如果的走得快的指针走到了链表的末尾都没有追上走得慢的指针,那么链表就不包含环。

  1. 找到环的入口

用两个指向头节点指针P1,P2,如果链表中的环有n个节点,则一个指针P1指针先向前移动n步,然后两个指针以相同的数据向前移动。当P2指向指向环的入口节点时,P1已经围绕环走了一圈,又回到了入口节点。

    3、计算环中节点数目

两个相遇的指针一定在环中,从这个节点出发,一边继续向前移动一边计数,再次回到这个节点时,可以得。

自己解题

没思路(两个指针还能这么用,wtf)

参考解题

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {

    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        // 输入头节点,返回环的入口节点,没环返回空
        //异常处理
        if(pHead == null){
            return null;
        }
        // 相遇节点
        ListNode meetingNode = MeetingNode(pHead);
        if(meetingNode  == null ){
            return null;
        }
        // 求环中节点数,nodesinLoop
        int nodesinLoop = 1;
        ListNode node = meetingNode;
        while(node.next != meetingNode){
            node = node.next;
            ++nodesinLoop;
        }
        // 根据环中节点数,找环切入口
        ListNode p1 = pHead;
        ListNode p2 = pHead;
        for(int i = 0 ; i < nodesinLoop; ++i){
            //先移动p1,nodesinLoop步
            p1 = p1.next;
        }
         while(p1 != p2){
             //再同时移动p1、p2,直到两者相遇,相遇时为环切入口
             p1 = p1.next;
             p2 = p2.next;
         }
        return p1;
    }
    
    // -----功能模块,求环中相遇节点---------------------
    public ListNode MeetingNode(ListNode pHead){
        //异常处理
        if(pHead == null || pHead.next == null){
            return null;
        }
        // 快慢指针定义
        ListNode slow = pHead.next;
        ListNode fast = slow.next;
        // 操作:判断是否有环,快2步,慢1步,直到相遇
        while(slow != null && fast != null){
            // 有环,返回相遇节点
            if(fast == slow){
                return fast;
            }
            slow = slow.next;
            fast = fast.next;
            if(fast.next != null){    // 增强 鲁棒性
                fast = fast.next;
            }
        }
        // 遍历完没相遇,没环
        return null;
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值