链表中环的入口结点(题号23)

2021-10-25  本文已影响0人  莺歌燕舞2018

问题描述:

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

数据范围: n≤1000

要求:空间复杂度 O(1),时间复杂度 O(n)

解题思路:

  1. hash

    遍历所有节点,将节点地址依次存储在一个hash表中,等走完环形部分回到环的入口节点处,此时hash表中已经存储过所有节点,经过判断是否存在该节点会返回true,则该节点就是入口节点,直接返回即可。

    时间复杂度:O(n)

    空间复杂度:O(n)

    该方法因为空间复杂度不满足要求,所以不做重点讲解

  2. 双指针法

    初始化两个节点指向链表头结点,一个步进快的fast,一个步进慢的slow,设定fast节点每次步进两步,slow节点每次步进一步。当两个节点第一次相遇(指向同一个节点,此时在环中)的时候,将其中一个节点重置为指向头结点然后分别以一为步长重新步进,待两个节点重新相遇,则被指向的节点就为环的入口节点。

    时间复杂度:O(n)

    空间复杂度:O(1)

    下面着重讲解该方法

注意事项:

跳出循环的判断条件以及跳出第一次循环后判断是否是正常跳出:正常跳出则返回null,表示没有环,打断则继续第二个循环

论证

代码

public class Solution {

    public ListNode EntryNodeOfLoop(ListNode pHead) {
        ListNode fast = pHead;
        ListNode slow = pHead;
        // 快速节点终止循环的条件是当前指向的节点为空或者当前节点的下一个节点为空
        while (fast != null && fast.next != null) {
            // 每次步进两步
            fast = fast.next.next;
            // 每次步进一步
            slow = slow.next;
            // 代表两节点第一次相遇
            if (fast == slow) {
                break;
            }
        }
        // 正常退出循环代表该链表无环,所以返回null
        if (fast == null || fast.next == null) {
            return null;
        }
        // 选择一个节点重置到链表头节点位置
        fast = pHead;
        // 分别重新以步长为一的速度步进直到两个节点重新相遇,终止循环
        while (fast != null && fast != slow) {
            fast = fast.next;
            slow = slow.next;
        }
        // 返回相遇位置的节点即为环的入口
        return slow;
    }
}
上一篇 下一篇

猜你喜欢

热点阅读