【剑指offer中等部分23】链表中环的入口结点(java)

一、题目描述

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

二、分析

方法一

找到环的入口结点,就是找到刚进入环的第一个结点,如下图,找入口结点就是找第一个发生重复的结点,那么我们又可以借鉴之前两个习题(中等20中等22)的思想,也就是用一个List集合,如果集合中不包含结点,就添加。如果集合中包含结点,那么就跳出循环,返回该结点,该目标结点即为第一个重复的结点,也就是入口结点,由于要遍历整个链表,故其时间复杂度为O(n2)。
在这里插入图片描述
实现代码如下:

import java.util.List;
import java.util.ArrayList;
public class Solution {

    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        ListNode targetNode = null;
        if(pHead == null || pHead.next ==null){
            return null;
        }
        List<ListNode> list = new ArrayList<ListNode>(); //集合中存放结点
        list.add(pHead); //添加头结点
        targetNode = pHead.next;
        // 判断是否存在环,即list中是否存在重复结点
        while(!list.contains(targetNode)){
            list.add(targetNode);
            targetNode = targetNode.next;
        }
        return targetNode;
    }
}

在这里插入图片描述

方法二

快慢指针(需要理解,但这个算法时间复杂度更低)
方法分两个步骤处理
1、设置两个指针,一个为快指针fast,一个为慢指针low,快指针一次走两步,慢指针一次一步,最后肯定会遇上。第一次遇上我们记为相遇点,此时快慢指针都指向这个相遇点
2、fast继续指向这个相遇点,但是让low指针指向链表头结点,此时快慢指针都一起每次走一步,最终他们会在入口结点相遇。
为什么这样会在入口结点相遇呢?我们带着这个问题进行推理分析一下,如下图
在这里插入图片描述
a,b,c分别为三个结点之间的距离
我们先讨论到相遇点,fast与low两指针走过的路程:
快指针路程 = a+(b+c)k+b ,k≥1,这表示至少一圈环,b+c为一个环的长度

慢指针路程 = a+b

由于快指针步长等于慢指针2倍,则
a+(b+c)k+b = 2(a+b),化简得a = (k-1)(b+c)+c,该式子意思是:
链表头到入口结点的距离 = 相遇点到入口结点的距离+(k-1)圈环长度

因此,在找到相遇点后,还需要将low重置到表头,继续每次走一步,这样得话,两个最后一定会在入口结点相遇,返回该结点即可

实现代码如下:

import java.util.List;
import java.util.ArrayList;
public class Solution {

    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        if(pHead == null|| pHead == null)
            return null;
        ListNode fast = pHead;
        ListNode low = pHead;
        //找相遇点
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            low = low.next;
            if(fast == low)
                break;
        }
        //相遇点非空
        if(fast == null|| fast.next == null)
            return null;
        low = pHead; //链表头出发
        while(fast != low){
            fast = fast.next;
            low = low.next;
        }
        return low;
    }
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小样x

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值