数据结构:链表带环问题的求解

这篇具有很好参考价值的文章主要介绍了数据结构:链表带环问题的求解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

数据结构:链表带环问题的求解,数据结构,链表,数据结构

个人主页 :个人主页
个人专栏 :《数据结构》《C语言》


一、确认链表带环

  • 思路
    我们定义两个变量,slow和fast,慢指针slow一次走一步,快指针fast一次走两步,则如果链表带环,slow和fast一定在环中相遇。思路很简单,但是为什么???

  • 解释1
    当slow刚进入环部分,fast与slow相距N个节点时。
    slow一次走一步,fast一次走两步。
    如下:
    数据结构:链表带环问题的求解,数据结构,链表,数据结构
    此时fast与slow的步长差是1。
    如果slow,fast先后移动一次,则fast与slow相距(N-1)个节点,若在进行一次,则fast与slow相距(N-2)个节点,循环往复则fast与slow终会相遇,也就是相距0个节点。
    如下:
    数据结构:链表带环问题的求解,数据结构,链表,数据结构
    所以slow与fast一定在环中相遇且不可能错过。

  • 延伸
    如果fast走n步(n > 2)?slow与fast还一定在环中相遇吗?

  • 解释2
    当slow刚进入环部分,fast与slow相距N个节点时。
    假设slow一次走一步,fast一次走3步。
    如下:
    数据结构:链表带环问题的求解,数据结构,链表,数据结构
    此时slow与fast的步长差是 2。

如果slow与fast先后移动一次,则slow与fast相距为(N-2),移动两次,相距为(N-4),循环往复,我们会发现当N是偶数时,slow与fast移动N/2次,相距为0,二者相遇。当N是奇数时,slow与fast移动N/2次,二者相距为1,slow与fast再次移动,则二则相距-1,也就是C(环的大小)-1。如果C-1是偶数,则slow与fast在移动(C-1)/2次,二者会相遇。如果C-1是奇数,则slow与fast再移动(C-1)/2次,二者还是相距-1,也就是说,二者会死循环,永远的错过。
如下:
数据结构:链表带环问题的求解,数据结构,链表,数据结构
也就是说,fast移动3步时,有可能会与slow永远错过不相遇。
那fast移动4步呢?
如下:
数据结构:链表带环问题的求解,数据结构,链表,数据结构
依次往后寻找,我们会发现只有当N时fast与slow步长差的整数倍时,slow与fast才会相遇

  • 代码实现
//141. 环形链表
bool hasCycle(struct ListNode* head) {
    struct ListNode* slow = head;
    struct ListNode* fast = head;

    if (head == NULL)
    {
        return false;
    }

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

        if (fast == slow)
        {
            return true;
        }
    }

    return false;

}

二、返回链表的头节点

1.公式法

情况如下:
数据结构:链表带环问题的求解,数据结构,链表,数据结构
也就是说,newhead与meet同时移动当二者相遇是,相遇的点就是链表圆环部分的头结点。

  • 代码如下:
142. 环形链表 II(返回环的头节点)
// 
// 公式法
// 到相遇的距离                         C是环的大小
// slow走的距离是L+X,fast走的距离是L+N*C+X
// 则2*slow == fast
//   2*(L + X) = L + N*C + X
//      L = N * C - X
//		L = (N - 1) * C + C - X
//		L = C - X
//链表除环的长度    相遇点到换头的距离  
//        
struct ListNode* detectCycle(struct ListNode* head) {
    struct ListNode* fast = head;
    struct ListNode* slow = head;

    if (head == NULL)
    {
        return NULL;
    }

    //外层循环找环
    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;

        if (slow == fast)
        {
            struct ListNode* meet = slow;
            struct ListNode* newhead = head;
            //找环头节点
            while (newhead != meet)
            {
                meet = meet->next;
                newhead = newhead->next;
            }

            return newhead;
        }
    }

    return NULL;
}

2.将问题转换成两个链表相交,求交点问题

  • 思路
    如果链表有环,也就是说fast与slow会相遇,那么我们将meet(相遇点)当成链表的尾节点,meet下一个节点当成新链表的头结点,让新的头节点与旧的头节点同时移动,当二者相遇是,相遇点就是链表环部分的头结点。
    如下:
    数据结构:链表带环问题的求解,数据结构,链表,数据结构

  • 代码如下


// 将找环头结点转化为两个链表相交问题
// 让slow与fast相遇的点做为两个链表的尾节点,meet的下一个节点作为其中一条链表的头结点
// 原链表的头结点是另一条链表的头结点
#include <stdlib.h>

struct ListNode* detectCycle(struct ListNode* head) {
    struct ListNode* fast = head;
    struct ListNode* slow = head;

    if (head == NULL)
    {
        return NULL;
    }
	//外层循环找是否有环
    while (fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
		
        if (fast == slow)
        {
            struct ListNode* list2 = slow->next;
            struct ListNode* list1 = head;
			
            int len1 = 0;
            int len2 = 0;
			
            while (list2 != slow)
            {
                list2 = list2->next;
                len2++;
            }
			
            while (list1 != slow)
            {
                list1 = list1->next;
                len1++;
            }
			//区分长和短的链表
            int differ = abs(len1 - len2);
            struct ListNode* longlist = head;
            struct ListNode* shortlist = slow->next;
			
            if (len1 < len2)
            {
                longlist = slow->next;
                shortlist = head;
            }
			//长的链表先走
            while (differ--)
            {
                longlist = longlist->next;
            }
			//两个链表同时移动
            while (longlist != shortlist)
            {
                longlist = longlist->next;
                shortlist = shortlist->next;
            }

            return longlist;
        }
    }

    return NULL;
}

总结

以上就是我对于链表带环方面的总结。
数据结构:链表带环问题的求解,数据结构,链表,数据结构

感谢各位佬的观看!!!文章来源地址https://www.toymoban.com/news/detail-626230.html

到了这里,关于数据结构:链表带环问题的求解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构 | 入门】线性表与链表 (问题引入&实现&算法优化)

    🤵‍♂️ 个人主页: @计算机魔术师 👨‍💻 作者简介:CSDN内容合伙人,全栈领域优质创作者。 本文是浙大数据结构学习笔记专栏 这里我们引入一个问题,最常见的多项式,我们如何使用编程将多项式表示出来呢? 我们可以使用数组来表示,但是会随着一个问题,如下图底

    2024年01月21日
    浏览(71)
  • C语言数据结构-用链表解决约瑟夫环问题

    只是普通的大学生一枚,不会很牛的技巧和算法,只是在做数据结构作业中的一点感悟和思考。也不知道自己写得对不对,有什么意见和建议都可以直接指出来哦,我虚心接受(低头鞠躬.jpg)...... 试用线性表的链表存储结构来实现约瑟夫(Josephu)问题。约瑟夫问题如下:设有

    2024年02月06日
    浏览(47)
  • 数据结构实验---顺序表的合并---链表的基本操作---重点解析约瑟夫问题

    实验的写法多种多样,但本文并未采用 #define 定义容量的写法,这样写已经是很老旧过时的写法。所有实验主体采用均为动态开辟,后续如果利用 C++ 来写或许会应用更多语法… 本篇展示数据结构的两个实验 其中,重点分析约瑟夫问题 实验中代码的命名风格等均与下方博客

    2024年02月16日
    浏览(62)
  • 【数据结构与算法】【约瑟夫问题】还在用递归?教你用链表秒杀约瑟夫

     🎉🎉欢迎光临🎉🎉 🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀 🌟特别推荐给大家我的最新专栏 《数据结构与算法:初学者入门指南》📘📘 本专栏纯属为爱发电永久免费!!! 这是苏泽的个人主页可以看到我其他的内容哦👇👇 努力的苏泽 http://su

    2024年02月19日
    浏览(39)
  • C语言---数据结构实验---顺序表的合并---链表的基本操作---重点解析约瑟夫问题

    实验的写法多种多样,但本文并未采用 #define 定义容量的写法,这样写已经是很老旧过时的写法。所有实验主体采用均为动态开辟,后续如果利用 C++ 来写或许会应用更多语法… 本篇展示数据结构的两个实验 其中,重点分析约瑟夫问题 实验中代码的命名风格等均与下方博客

    2024年02月16日
    浏览(70)
  • 数据结构--迷宫求解

    文章目录 一、问题的描述 二、系统功能设计 三、各个代码部分 四、整体代码及其运行 五、总结 迷宫求解--C语言 在一个迷宫中,需要我们找到出去的道路,并且得到的路经是最短的。 迷宫设置如下:迷宫使用标记(0,1,2,3分别代表迷宫的墙壁,通道,入口和出口) 从开

    2024年02月15日
    浏览(40)
  • 迷宫求解(包含随机迷宫、求解动画演示)——C语言 数据结构

    该程序是一项 “迷宫求解” 类问题,主要功能包含:         ①25 X 25迷宫的随机生成         ②迷宫求解的动画演示(DFS) 完整代码附最后 : ) 功能演示: 界面展示:  迷宫展示: 结果展示:   首先是随机迷宫部分: 大概思路就是先初始化一个矩阵,外圈为“通

    2024年02月07日
    浏览(65)
  • 数据结构-链表结构-双向链表

    双向链表也叫双链表,与单向链表不同的是,每一个节点有三个区域组成:两个指针域,一个数据域 前一个指针域:存储前驱节点的内存地址 后一个指针域:存储后继节点的内存地址 数据域:存储节点数据 以下就是双向链表的最基本单位 节点的前指针域指向前驱,后指针

    2024年02月04日
    浏览(47)
  • <数据结构> 链表 - 链表的概念及结构

    概念: 链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的 逻辑顺序 是通过链表中的 指针链接 次序实现的 1、链表由一系列结点(链表中每一个元素称为结点)组成。 2、结点可以在运行时动态(malloc)生成。 3、每个结点包括两个部分:一个是存储数据元素的

    2023年04月09日
    浏览(46)
  • 【数据结构题目讲解】BZOJ 3306 - 树 利用DFS序求解

    D e s c r i p t i o n mathrm{Description} Description 给定 1 1 1 棵以 1 1 1 为根节点的 n n n 个点的树,接下来有 m m m 次操作: V x y 将 x x x 点的权值更改为 y y y E x 将根改为 x x x 点 Q x 查询 x x x 子树的最小值 S o l u t i o n mathrm{Solution} Solution 首先,考虑如果没有换根操作(即 E 操作),那

    2024年02月19日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包