如何通过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#操作本地文件及保存文件到数据库的基本方法总结 操作本地文件是开发中经常需要处理的事情,而保存文件到数据库则会更加复杂,因此本文总结了C#操作本地文件及保存文件到数据库的基本方法。 操作本地文件 在C#中,我们可以使用System.IO命名空间下的类来操作本地文件。下面是一些常见的操作示例: 创建一个新文件 string filePath = @&quot…

    C 2023年5月22日
    00
  • c++对象内存布局示例详解

    首先,让我们来了解一下C++对象的内存布局。在实际编程中,我们经常会涉及到创建对象,并根据对象来进行操作。因此,了解对象在内存中所占的布局情况,对于有效地管理内存使用以及提高代码执行效率都很有帮助。 C++对象内存布局包括以下三个部分: 对象的数据成员 对象的虚函数表指针 (vptr) 对象的填充字节 数据成员是对象实际存储数据的部分,虚函数表指针用于处理虚…

    C 2023年5月22日
    00
  • 详解C++程序中定义struct结构体的方法

    下面我将详细讲解如何在C++程序中定义struct结构体。 1. 概述 在C++中,struct是一种用户自定义的数据类型,它可以将多个不同类型的数据成员组合在一起,形成一个数据结构。在C++中,我们可以使用struct关键字来定义一个结构体,然后在程序中实例化一个结构体对象,可以使用结构体对象来访问结构体中的数据成员,从而完成对数据的处理。 2. 定义结构…

    C 2023年5月30日
    00
  • 浅谈html特殊字符 编码css3 content:”我是特殊符号”

    下面是关于”浅谈HTML特殊字符编码CSS3 content”的攻略: HTML特殊字符 在HTML中,有一些字符是有特殊含义的,例如<和>用于表示标签的开始与结束,如果我们想要在HTML中显示这些字符本身,就需要使用特殊字符。 特殊字符使用&和;来表示,其中&为特殊字符的开始标记,;为特殊字符的结束标记。例如,&lt;表…

    C 2023年5月22日
    00
  • C++如何调用opencv完成运动目标捕捉详解

    C++如何调用OpenCV完成运动目标捕捉,以下是详细攻略。 准备工作 在使用OpenCV前,需要安装OpenCV库。可以从OpenCV的官方网站(https://opencv.org/)下载,安装后需要在编译时链接到相关的库文件。 加载视频文件 首先需要加载视频文件,使用OpenCV中的cv::VideoCapture类。该类的构造函数接受视频文件路径作为…

    C 2023年5月23日
    00
  • c++ 让程序开机自动启动的方法

    当我们想让编写的c++程序自动启动时,可以采用下面几种方法来实现。 方法一:修改注册表 假设我们要设置的程序名为 test.exe,要将其设置为系统开机启动的程序。可以使用以下步骤: 打开注册表编辑器:在开始菜单中输入 regedit,打开注册表编辑器。 找到启动项:依次展开 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft…

    C 2023年5月23日
    00
  • Turbo C 2.0使用教程图文版(使用Turbo C 2.0编写C语言程序)

    Turbo C 2.0使用教程图文版(使用Turbo C 2.0编写C语言程序) 介绍 Turbo C 2.0是一款老式的C语言编程软件,在过去曾经非常受欢迎。尽管目前有更为现代的C语言编程工具,但Turbo C 2.0仍然是一个非常不错的编程工具。在这里,我们将介绍如何使用Turbo C 2.0编写C语言程序。 下载和安装Turbo C 2.0 Turbo…

    C 2023年5月23日
    00
  • Cs全面介绍与问题解答

    Cs全面介绍与问题解答 什么是Cs? Cs是Counter-Strike的缩写,是一款经典的多人游戏。游戏的核心玩法包括恐怖分子与反恐精英之间的对抗。两支队伍都会获得特定的任务,如拆弹、营救人质等。游戏时间较短,每局游戏通常为1分钟到3分钟。 Cs的游戏模式 团队对抗:恐怖分子与反恐精英之间的经典对抗。 成人礼:一名护送者护送一名新兵从一个地点到另一个地点,…

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