每天一道剑指offer-链表中环的入口结点

考试结束,班级平均分只拿到了年级第二,班主任于是问道:大家都知道世界第一高峰珠穆朗玛峰,有人知道世界第二高峰是什么吗?正当班主任要继续发话,只听到角落默默响起来一个声音:”乔戈里峰

题目

每天一道剑指offer-链表中环的入口结点 https://www.nowcoder.com/practice/253d2c59ec3e4bc68da16833f79a38e4?tpId=13&tqId=11208&tPage=3&rp=3&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

题目详述

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

题目详解

思路

  • 使用快慢指针,快指针每次走两步,慢指针每次走一步,如果快慢指针相遇说明有环;

  • 有环以后,需要寻找环入口节点,已经找到了一个环的中的节点,利用这个节点,去往下遍历,由于是环,所以这个节点肯定会和自身相遇,相遇以后,记录相遇过程中走的步数,就是环的长度

  • 知道环的长度以后,然后再利用快慢指针的思想,快指针先走环长度,然后快慢指针再一起走,这样因为快指针先走了环的长度,当两者相遇肯定是环的入口节点相遇(为啥呢,因为快慢指针肯定会进入环里面,而由于快指针先走了环的长度,所以也就是一个周期,所以只要进入环,那么这两个指针必然相遇)

代码

/*	
 public class ListNode {	
    int val;	
    ListNode next = null;	
    ListNode(int val) {	
        this.val = val;	
    }	
}	
*/	
public class Solution {	
    boolean flag = true;	
    public ListNode EntryNodeOfLoop(ListNode pHead)	
    {	
        if(pHead == null || pHead.next == null)	
            return null;	
        ListNode pNode = judgeHasChain(pHead);//判断是否有环	
        if(pNode != null)	
        {	
            int lengthChain = 1;	
            ListNode pNodeCopy = pNode.next;	
            while(pNodeCopy != pNode)	
            {//这个节点已经在环里面了!	
                lengthChain++;	
                pNodeCopy = pNodeCopy.next;//计算环的长度	
            }	
            ListNode fast = pHead;	
            ListNode slow = pHead;	
            int temp = 0;	
            while(temp < lengthChain)	
            {//快指针先走环的长度	
                fast = fast.next;	
                temp++;	
            }	
            while(fast != slow)	
            {//快慢指针一起走,因为快指针先走了环长度,当慢指针刚一进环,由于快指针刚好多走了环长度,所以快指针整好走了一个环的周期呀,所以快指针必然也在环的入口	
                fast = fast.next;	
                slow = slow.next;	
            }	
            return fast;	
        }	
        return null;	
    }	
    private ListNode judgeHasChain(ListNode pHead)	
    {	
        ListNode fast = pHead.next;	
        ListNode slow = pHead;	
        while(fast != slow)	
        {	
            if(fast != null && fast.next != null)	
            {//快指针走一步	
                fast = fast.next;	
            }else{	
                flag = false;	
                break;	
            }	
            if(slow != null && slow.next != null)	
            {//慢指针走一步	
                slow = slow.next;	
            }else{	
                flag = false;	
                break;	
            }	
            if(fast == slow)	
            {//两者相等,说明相遇了,有环	
                return fast;	
            }else{	
                fast = fast.next;//快指针多走一步	
            }	
        }	
        if(flag)	
            return fast;	
        return null;	
    }	
}

结束语

作者乔戈里亲历2019秋招,哈工大计算机本硕,百度java工程师,欢迎大家关注我的微信公众号:程序员乔戈里,公众号有3T编程资源,以及我和我朋友(百度C++工程师)在秋招期间整理的近200M的面试必考的java与C++面经

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值