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

yizhihongxing

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日

相关文章

  • AI绘制一副潜水员深海冒险场景插画教程

    标题:AI绘制一副潜水员深海冒险场景插画教程 正文:本教程将介绍如何使用AI绘制一副潜水员深海冒险场景插画,具体步骤如下: 准备工作 下载并安装AI设计软件(如Adobe Illustrator) 准备相关素材(如潜水员图片、深海生物图片、海底场景图片等) 绘制潜水员 打开AI设计软件,并导入潜水员图片 选择画笔工具,对潜水员进行描边和填充操作,注意保留细节…

    C 2023年5月22日
    00
  • Autoruns怎么用?Autoruns详细图文教程

    Autoruns是一款系统工具软件,它可以用来查看Windows操作系统启动时会自动运行的进程,服务,驱动程序以及其他自启动项。下面将为大家提供一份Autoruns详细图文教程,让大家了解如何使用它。 Autoruns怎么用? 首先下载Autoruns软件并安装,这里提供官方下载地址:https://docs.microsoft.com/en-us/sysi…

    C 2023年5月23日
    00
  • VC List Control控件如何删除选中的记录实例详解

    删除VC List Control控件中选中的记录的过程可以通过以下步骤实现: 获取选中的记录索引:可以通过List Control控件的GetNextItem函数来获取选中的记录索引。该函数的参数可以用来指定搜索的起始索引。因此,我们可以在循环中使用该函数来获取所有选中的记录索引。 示例代码: int nItem = -1; while ((nItem =…

    C 2023年5月23日
    00
  • C语言中条件编译详解

    关于“C语言中条件编译详解”的攻略,我会详细讲解如下: 什么是条件编译? 条件编译就是根据某些条件来判断编译是否要执行某个代码块,也就是说可以根据不同的条件来编译不同的程序。 条件编译的语法 在 C 语言中,我们使用预处理器来实现条件编译,其语法如下: #ifdef macro // do something #endif 其中,“#ifdef”是条件编译的…

    C 2023年5月23日
    00
  • 详解MySQL 数据库隔离级别与MVCC

    详解 MySQL 数据库隔离级别与 MVCC MySQL 是一种开源的关系型数据库管理系统,支持多种隔离级别和多版本并发控制(MVCC)。这篇文章将详细讲解 MySQL 数据库隔离级别和 MVCC 的相关知识。 MySQL 数据库隔离级别 MySQL 数据库支持多种隔离级别,包括读未提交(READ UNCOMMITTED)、读已提交(READ COMMITT…

    C 2023年5月22日
    00
  • C语言中如何控制程序流程?

    控制程序流程是C语言中非常重要的一个方面,主要通过条件语句、循环语句以及函数调用来实现。下面我将详细讲解。 条件语句 条件语句用于根据条件来执行不同的代码块。C语言中,最常用的条件语句为if…else语句和switch语句。 if…else语句 if…else语句用于在满足特定条件时执行代码块。如果条件为真,则执行if代码块,否则执行else代码…

    C 2023年4月27日
    00
  • 从Immutable.js到Redux函数式编程

    从Immutable.js到Redux函数式编程的完整攻略包含以下步骤: 1. 简介 Immutable.js是一个JS库,提供了一组不可变数据结构集合(如List、Map、Set等),可以帮助我们更简洁、高效地处理数据,同时避免出错。而Redux是一个用于JavaScript应用程序的可预测状态容器,可以确保你的应用的行为始终一致且易于测试。借助Immut…

    C 2023年5月22日
    00
  • 用C编写一个送给女朋友的情人节小程序 可爱!

    下面是“用C编写一个送给女朋友的情人节小程序 可爱!”的完整攻略: 目录 情人节小程序的设计思路 需要用到的C语言知识点 编写情人节小程序的步骤 示例说明 总结 情人节小程序的设计思路 情人节小程序是一款可爱的程序,旨在表达爱意。程序设计的主要部分是一个心形的图案,图案中有两个小人围绕一个爱心旋转,表示两个人相互依存,互相照顾,不离不弃的爱情。同时,程序还会…

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