【牛客101】06,07判断链表中是否有环,找到环的入口


1. 判断是否有环

1.1 题目描述

判断给定的链表中是否有环。如果有环则返回true,否则返回false。

数据范围:链表长度 0 \le n \le 100000≤n≤10000,链表中任意节点的值满足 |val| <= 100000∣val∣<=100000
要求:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)

输入分为两部分,第一部分为链表,第二部分代表是否有环,然后将组成的head头结点传入到函数里面。-1代表无环,其它的数字代表有环,这些参数解释仅仅是为了方便读者自测调试。实际在编程时读入的是链表的头节点。
在这里插入图片描述

1.2 题目分析

这个分析还有点难想到.我们这里设置一个快节点,每次走两步,fastNode = fastNode.next.next;慢节点每次走一步,slowNode = slowNode.next;假设有一个环形跑道,有两人在同一起跑线出发,一个人跑得快,一个人跑得慢,那么,这两个人肯定会相遇.所以,如果链表有环的话,fastNode 与 slowNode 一定会相遇,也就是
fastNode == slowNode;

1.3 代码讲解

这里需要注意的是,循环的条件中,由于fast走在slow的前面,所以,如果fastNode != null时.slowNode也不会为null.另外,除了要控制fast != null外,由于引用了fast.next的next,所以需要判断一下fast.next是否为空.

public class Solution {
    public boolean hasCycle(ListNode head) {
       ListNode fast = head;
    	ListNode slow = head;
    	while(fast != null && fast.next != null){
        	fast = fast.next.next;
        	slow = slow.next;
        	if(fast == slow){
            	return true;
        	}
    	}
    	return false;
    }
}

2. 找到环的入口

2.1 题目描述

给一个长度为n链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。

数据范围: 10000n≤10000,1<=结点值<=10000
要求:空间复杂度 O(1),时间复杂度 O(n)
在这里插入图片描述

2.2 问题分析

这个题的做法有点难想,这个是使用了数学问题加以解决的.
如下图所示,若有两个节点从head处出发,fast节点的速度是slow节点的2倍,二者在相遇处相遇,那么,通过解一个方程.

如图,快节点的路程为-------x + 环的总长度 + 环长度 - y
慢节点的路程为------------- x + 环长度 - y

快节点的路程 = 慢节点的路程 x 2
设环的总长度为n

x + n + n - y = 2 * (x + n - y)
x + 2n -y = 2x + 2n - 2y
x = y

在这里插入图片描述
所以,在fast,slow相遇后,令slow从head处出发,与fast以同一速度前进,相遇处就是环的入口处.

2.3 代码详解

没啥好说得了,注意如果链表没有环,要返回null.

public ListNode EntryNodeOfLoop(ListNode pHead) {
        //找环的入口处,也就是跑道的入口处,返回入口节点
        //找环的入口点,起始点到入口点的距离与相遇点到入口距离相等,找到相遇点.
        //让slow回到head,同fast一起走,相遇的点为环入口
        ListNode fast = pHead;
        ListNode slow = pHead;
        while(fast != null && fast.next != null){
            slow = slow.next;
            fast = fast.next.next;
            if(fast == slow){
                slow = pHead;
                while(slow != fast){
                    slow = slow.next;
                    fast = fast.next;
                }
                return slow;
            }
        }
        return null;
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值