剑指offer 面试题23:链表中环的入口节点(java)

题目:

  给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

思路:
  1.如何确定一个链表中包含环:
    定义两个指针,同时从链表的头节点出发,一个指针一次走一步,另一个一次走两步如果走的快的指针追上了走的慢的指针,就说明链表包含环。

  如果链表中有环
   计算环中节点的个数:
    因为在判断链表中是否有环时,当两个指针相遇时,说明有环,而且两个指针相遇的节点肯定在环中,从当前这个节点再进行移动,边移动边计数,当再次回到这个点时,就得到环中节点的个数。

  2.如何找到环出口:
   先定义两个指针p1,p2,指向链表的头节点。
   如果链表中的环有n个结点
   先将p1在链表上向前移动n个节点。
   然后两个节点相同速度移动,当p1的位置跟p2相等时,说明p1,p2到了入口节点
   因为p2到入口节点时,p1已经绕环走了一圈


代码

public static class ListNode{
        int m_value;
        ListNode m_pNext;
        ListNode(int m_value){
            this.m_value=m_value;
        }
    }
   
    //判断是否是环
    public static ListNode MeetingNode(ListNode pHead){
        if(pHead==null)
            return null;
        ListNode pSlow=pHead.m_pNext;
        if(pSlow==null)
            return null;
        ListNode pFast=pSlow.m_pNext;
        while (pFast != null && pSlow != null){
            if(pFast==pSlow)
                return pFast;
            pSlow=pSlow.m_pNext;
            pFast=pFast.m_pNext;
            if(pFast!=null){
                pFast=pFast.m_pNext;
            }
        }
        return null;
    }
    //找出环的入口节点
    public static ListNode EntryNodeOfLoop(ListNode pHead){
        ListNode meetingNode=MeetingNode(pHead);
        if(meetingNode==null){
            return null;
        }
        //计算环中节点的数目
        int nodesInLoop=1;
        ListNode pNode1=meetingNode;
        while (pNode1.m_pNext!=meetingNode){
            pNode1=pNode1.m_pNext;
            ++nodesInLoop;
        }
        //先移动pNode1,次数为环中节点的数目
        pNode1=pHead;
        ListNode pNode2=pHead;
        for(int i=0;i<nodesInLoop;i++){
            pNode1= pNode1.m_pNext;
        }
        //再移动pNode1和pNode2
        while (pNode1!=pNode2){
            pNode1=pNode1.m_pNext;
            pNode2=pNode2.m_pNext;
        }
        return pNode1;
    }
     public static void main(String[] args) {
        ListNode node1=new ListNode(1);
        ListNode node2=new ListNode(2);
        ListNode node3=new ListNode(3);
        ListNode node4=new ListNode(4);
        ListNode node5=new ListNode(5);
        ListNode node6=new ListNode(6);
        node1.m_pNext=node2;
        node2.m_pNext=node3;
        node3.m_pNext=node4;
        node4.m_pNext=node5;
        node5.m_pNext=node6;
        node6.m_pNext=node3;
        ListNode result = EntryNodeOfLoop(node1);
        if(result==null){
            System.out.println("此链表不是环");
        }else {
            System.out.println("入口节点是:"+result.m_value);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值