如何通过C++求出链表中环的入口结点

1. 环的入口结点(题目描述)

给定一个链表,返回链表中环的入口结点。如果链表无环,则返回 NULL

要求算法的空间复杂度为 O(1)。

2. 思路分析

这道题可以使用双指针法(快慢指针)来解决。

具体的思路为:首先,设定两个指针,分别为 fastslow,然后,让它们以不同的速度往前走(fastslow 快),这样,当两个指针重合时,就表示链表中存在环。

接着,我们需要找到环的入口结点。首先,设集合 S 表示所有从链表头结点到环的入口结点的结点集合,当 slowfast 指针第一次相遇时,fast 指针一定比 slow 指针多走一圈。设链表头结点到环的入口结点的长度为 x,环的周长为 y,则:

  1. slowfast 指针相遇时,slow 走过的路程长度为 x + n_1*yfast 走过的路程长度为 x + n_2*y
  2. 因为 fastslow 快一倍,所以 fast 走过的路程长度是 slow 走过的路程长度的两倍,即:

(x + n_2*y) = 2 * (x + n_1*y)

可化简得:

x = (n_2 - 2 * n_1) * y

接下来,设 a 和 b 分别为 slowfast 指针相遇点到环的入口结点的长度和起点到环的入口结点的长度,则:

  1. slow 指针从起点开始的路程长度为 x + a
  2. fast 指针从起点开始的路程长度为 x + b
  3. 因为 fastslow 快一倍,所以 fast 跑完整个环的时间是 slow 的两倍,所以从相遇点出发的距离等于起点到环入口的距离,即:

    a + y = b

    可以得到以下结论:
    x = (n_2 - 2 * n_1) * y
    a + y = b

接下来,我们可以从链表头结点开始,同时移动 slowfast 指针,每次移动一步,当两者相遇时,就表示它们相遇的结点即为环的入口结点。

3. 代码实现及示例说明

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* entryNodeOfLoop(ListNode* head) {
        if (head == nullptr || head->next == nullptr)
            return nullptr;

        ListNode* slow = head;
        ListNode* fast = head;

        while (fast != nullptr && fast->next != nullptr) {
            slow = slow->next;
            fast = fast->next->next;

            if (slow == fast) {
                fast = head;

                while (fast != slow) {
                    fast = fast->next;
                    slow = slow->next;
                }

                return fast;
            }
        }
        return nullptr;
    }
};

示例1:输入一个带环的链表,请输出该链表的环的入口结点。

1 -> 2 -> 3 -> 4 -> 5 -> 2

期望的输出结果为:2。

示例2:输入一个无环的链表,请输出 NULL

1 -> 2 -> 3 -> 4 -> 5

期望的输出结果为:NULL

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:如何通过C++求出链表中环的入口结点 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • C++课程设计之学生成绩管理系统

    C++课程设计之学生成绩管理系统攻略 1. 系统设计思路 学生成绩管理系统主要分为三个部分:学生信息管理、课程信息管理与成绩信息管理。本设计中,我们采用C++语言实现该系统。 学生信息管理:包括学号、姓名、性别、年龄等信息; 课程信息管理:包括课程名、课程编号、开课学期等信息; 成绩信息管理:包括学号、课程名、成绩等信息。 在该系统设计中,我们采用文件读写实…

    C 2023年5月23日
    00
  • json中换行符的处理方法示例介绍

    对于”json中换行符的处理方法示例介绍”这个话题,下面我将进行详细讲解。 1. 问题描述 在JSON数据中,如果包含了换行符,我们在解析JSON字符串的时候很有可能会遇到一些问题。因此需要对JSON字符串中的换行符进行处理,以避免出现解析JSON时出错的情况。 2. 处理方法 2.1 用转义字符代替换行符 JSON字符串中的换行符可以用转义字符\n代替,这…

    C 2023年5月23日
    00
  • C语言实现链队列

    接下来我将详细讲解“C语言实现链队列”的完整攻略。 什么是链队列 链队列是一种基于链表的队列实现,其底层数据结构为一个链表。相比于数组实现的队列,链队列具有动态分配内存空间的优势。链队列的队首与队尾分别指向链表的首尾节点,数据元素按顺序排列,后进先出。 实现链队列的步骤 1. 定义队列结构体 首先,需要定义队列结构体,包括队列的基本属性和操作方法: // 定…

    C 2023年5月23日
    00
  • 16种C语言编译警告(Warning)类型的解决方法

    16种C语言编译警告(Warning)类型的解决方法 编写代码时,编译器经常会发出警告。这些警告不一定表示代码有错误,但警告应该受到注意并解决。本文将介绍C语言编译警告的16种类型以及如何解决它们。 1. 程序参数不匹配 int main() { printf("hello World\n"); return 0; } 警告信息:warn…

    C 2023年5月23日
    00
  • 深入了解C语言中的const和指针

    深入了解C语言中的const和指针 概述 在C语言中,const和指针是两个比较常用的概念。本篇攻略将会深入讲解const和指针的相关知识,希望读者可以从中收获一些有用的知识。 const const 的定义 const是C语言中一个关键字,用来修饰一个变量,表示该变量是不可修改的。常见的用法如下: const int n = 10; 上述代码中,n是一个整…

    C 2023年5月23日
    00
  • vscode和cmake编译多个C++文件的实现方法

    针对”vscode和cmake编译多个C++文件的实现方法”这个问题,我将提供详细的攻略如下。 1. 建立项目 首先,在VS Code中选择一个空文件夹作为你的项目,使用快捷键 Ctrl + Shift + P 或者点击左侧的终端->新建终端(Terminal),打开终端面板并输入以下命令,初始化你的C++项目: mkdir build cd buil…

    C 2023年5月23日
    00
  • 乐玩2C后盖怎么打开 TCL乐玩2C手机打开后盖方法图解

    TCL乐玩2C手机后盖打开方法 前言 TCL乐玩2C是一款较为受欢迎的手机,但是许多用户可能都会遇到不知道如何打开后盖的问题。在此,本文将详细讲解乐玩2C手机如何打开后盖。 注意事项 在操作前请确保手机已关闭,并且拆卸后盖可能会对手机造成损害,请谨慎操作。建议您在比较熟悉的环境下进行拆卸。 操作步骤 步骤1:准备工具和材料 你需要先准备一把打开手机后盖的工具…

    C 2023年5月23日
    00
  • iOS 14.3/iPadOS 14.3开发者预览版 Beta 2(18C5054c)怎么升级?

    下面是 iOS 14.3/iPadOS 14.3 开发者预览版 Beta 2 升级的完整攻略,包括两条示例说明: iOS 14.3/iPadOS 14.3 开发者预览版 Beta 2 升级攻略 1. 准备工作 在升级前,请务必备份你的设备数据以防意外情况发生。此外,为了能够顺利升级,你还需要: 确保你的设备支持升级到 iOS/iPadOS 14.3 开发者预…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部