码迷,mamicode.com
首页 > 其他好文 > 详细

剑指Offer对答如流系列 - 链表中环的入口节点

时间:2020-01-31 21:06:48      阅读:75      评论:0      收藏:0      [点我收藏+]

标签:位置   try   问题   slow   detail   code   shadow   article   计算   

面试题23:链表中环的入口节点

问题描述

一个链表中包含环,如何找出环的入口结点?例如,在图中的链表中,环的入口结点是结点3。
技术图片
链表的结构

    public class ListNode {
            int val;
            ListNode next = null;
            
            ListNode(int val) {
                this.val = val;
            }
     }

问题分析

首先不能忽略链表中不包含环的情况,第一件事情必须先确定链表是否有环:我们可以使用两个引用,一个跑的快、一个跑的慢,同时出发,跑的快的追上跑的慢的自然说明有环。(术语是常说的快慢引用)

如果链表有环,第二件事是确定链表中的环节点的个数,在第一件事情中,快引用追上了慢引用,以追上的位置为起点(肯定在环中),走一圈,边走边计数。

现在问题转换为求 链表中倒数第k个结点。k的值为链表中环的长度。

问题解答

    public ListNode entryNodeOfLoop(ListNode head) {
        // 判断是否有环
        ListNode meetingNode=meetingNode(head);
        if(meetingNode==null) {
            return null;
        }

        //计算环中结点的数目
        int count=1;
        ListNode pNode1 = meetingNode.next;
        while(pNode1!=meetingNode){
            count++;
            pNode1=pNode1.next;
        }

        // 求链表中倒数第k个结点
        pNode1=head;
        for(int i=1;i<=count;i++) {
            pNode1=pNode1.next;
        }
        ListNode pNode2=head;
        while(pNode1!=pNode2) {
            pNode1=pNode1.next;
            pNode2=pNode2.next;
        }
        return pNode1;
    }

    private ListNode meetingNode(ListNode head) {
        if(head==null) {
            return null;
        }
        ListNode pSlow=head;
        ListNode pFast=head;
        while(pFast!=null) {
            pSlow=pSlow.next;
            pFast=pFast.next;
            if(pFast!=null) {
                pFast=pFast.next;
            }
            if(pSlow!=null && pSlow==pFast) {
                return pSlow;
            }
        }
        return null;
    }

剑指Offer对答如流系列 - 链表中环的入口节点

标签:位置   try   问题   slow   detail   code   shadow   article   计算   

原文地址:https://www.cnblogs.com/JefferyChenXiao/p/12246351.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!