【数据结构算法经典题目刨析(c语言)】环形链表的约瑟夫问题(图文详解)

news2024/11/14 20:55:02

💓 博客主页:C-SDN花园GGbond

⏩ 文章专栏:数据结构经典题目刨析(c语言)

一.前言: 

前言——著名的Josephus问题

据说著名犹太 Josephus有过以下的故事:在罗⻢⼈占领乔塔帕特后,39个犹太⼈与Josephus及他的朋友躲到⼀个洞中,39个犹太⼈决定宁愿死也不要被⼈抓到,于是决定了⼀个⾃杀 ⽅式,41个⼈排成⼀个圆圈,由第1个⼈开始报数,每报数到第3⼈该⼈就必须⾃杀,然后再由下⼀ 个重新报数,直到所有⼈都⾃杀⾝亡为⽌。 历史学家 然⽽Josephus和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与⾃⼰安排在 第16个与第31个位置,于是逃过了这场死亡游戏。

 二.题目描述:

三.题目解析 

题目的意思就是从环形链表的第一个节点开始数,数到第 m 的时候释放对应的节点,然后从下个节点又从1开始数,然后继续释放节点。所以我们要做的就是通过循环不断删除指定位置的节点。比如有5个节点,在删除第二个节点之前,得先让第一个节点的 next 指向第三个。
不过题目现在还没有链表,我们得先来创建一个。

下面这个图演示有五个节点,m = 2的情况 

 图解:

四.解题思路 

解决思路是用环形链表来模拟报数和离开
解决问题分三步
1. 实现申请单个环形链表的方法
2.创建环形链表
3.对链表循环遍历,实现报数和删除,返回最后剩下的节点的编号
 

 五.解题步骤

1.实现申请单个环形链表的方法 


动态申请一块节点大小的空间,并对数据和指针初始化(数据部分存储节点的编号,指针部分指向节点自身,默认自循环)
返回创建节点的地址

struct ListNode
{   //链表结构
    int val;
    struct ListNode* next;
};
typedef struct ListNode ListNode;//类型重定义
ListNode* NewNode(int a)//申请单个链表节点
{
    ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
    if (newnode == NULL)
    {
        exit(1);
    }
    newnode->val = a;
    newnode->next = newnode;//默认节点自循环
    return newnode;
}
2.创建环形链表


a. 先创建第一个节点作为首节点,创建首尾指针都指向该节点

(先单独创建一个节点,是因为根据题目描述,链表至少有一个节点,并且先单独申请一个节点可以保证链表不会空,省去后面申请节点时对链表判空的步骤)

b. 然后循环创建n个节点,尾插在链表上
c. 出循环后,把尾节点的next指针指向首节点
d. 返回链表的尾指针(返回尾指针是因为下一步骤要删除链表某个节点需要找到它的前一个节点,而环形链表返回尾指针可以同时获得尾节点和首节点)

ListNode* CreatList(int n)//根据n创建环形链表
{
    ListNode* phead = NewNode(1);//创建链表第一个节点
    ListNode* ptail = phead;
    for (int i = 2; i <= n; i++)//将新节点尾插到链表
    {
        ListNode* newnode = NewNode(i);
        ptail->next = newnode;
        ptail = ptail->next;
    }
    ptail->next = phead;//成环
    return ptail;//返回尾指针相当于得到了尾指针和头指针
}
 3.对链表循环遍历,实现删除,

a. 首先创建遍历指针的前一个节点的指针,初始指向尾节点

创建遍历链表的指针,初始指向尾节点的下一个节点,也就是首节点
创建一个计数器,初始为1

b. 进入while循环(循环执行的条件是遍历链表的指针所指向的节点的next指针不指向它自己,也就是说链表只有一个节点时结束循环)
循环内部,对计数器进行判断
如果计数器等于要报的数m,删除该节点,计数器重置为1
如果不等于要报数的m,两个指针向后移动,计数器++

c. 退出循环时,返回最后剩下的节点所对应的编号

注意:
返回编号之前不要忘记释放最后一个节点动态申请的空间

int ysf(int n, int m)
{
    ListNode* prev = CreatList(n);//创建环形链表,和指向前一个节点的指针
    ListNode* pcur = prev->next;//创建遍历链表的指针
    int count = 1;
    while (pcur->next != pcur)//循环结束的条件是某个节点自循环
    {
        if (count == m)//如果报数到m,删除节点
        {
            prev->next = pcur->next;
            free(pcur);
            pcur = prev->next;
            count = 1;
        }
        else //如果不是m,指针移动,计数器++
        {
            prev = pcur;
            pcur = pcur->next;
            count++;
        }
    }
    int ret = pcur->val;
    free(pcur);
    pcur = NULL;
    return ret;
}

六:完整代码实现 

struct ListNode
{   //链表结构
    int val;
    struct ListNode* next;
};
typedef struct ListNode ListNode;//类型重定义
ListNode* NewNode(int a)//申请单个链表节点
{
    ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
    if (newnode == NULL)
    {
        exit(1);
    }
    newnode->val = a;
    newnode->next = newnode;//默认节点自循环
    return newnode;
}
ListNode* CreatList(int n)//根据n创建环形链表
{
    ListNode* phead = NewNode(1);//创建链表第一个节点
    ListNode* ptail = phead;
    for (int i = 2; i <= n; i++)//将新节点尾插到链表
    {
        ListNode* newnode = NewNode(i);
        ptail->next = newnode;
        ptail = ptail->next;
    }
    ptail->next = phead;//成环
    return ptail;//返回尾指针相当于得到了尾指针和头指针
}
int ysf(int n, int m)
{
    ListNode* prev = CreatList(n);//创建环形链表,和指向前一个节点的指针
    ListNode* pcur = prev->next;//创建遍历链表的指针
    int count = 1;
    while (pcur->next != pcur)//循环结束的条件是某个节点自循环
    {
        if (count == m)//如果报数到m,删除节点
        {
            prev->next = pcur->next;
            free(pcur);
            pcur = prev->next;
            count = 1;
        }
        else //如果不是m,指针移动,计数器++
        {
            prev = pcur;
            pcur = pcur->next;
            count++;
        }
    }
    int ret = pcur->val;
    free(pcur);
    pcur = NULL;
    return ret;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1976450.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ansible 配置yum源

ansible配置yum源 有两种方式&#xff0c;一种是可以写好sh脚本&#xff0c;然后ansible去执行sh文件 另外一种就是使用yum_repository库 本文讲使用库的方式 本文使用的环境是centos7 &#xff0c;配置也是按照7去配置的&#xff0c;没有写动态配置 直接上代码 [rootvm-2 ~…

《技术人求职之道》之求职机遇篇:多渠道并进,如何高效获取面试机会

摘要 本文探讨了求职过程中获取面试机会的多种途径,强调简历优化的重要性,并指出了不同求职方式的优劣及其适用情况。文章首先介绍通过企业挖掘、内部推荐、猎头服务、社会招聘和校园招聘等途径获得面试机会的方法,并根据成功率和适用性为这些方法排序。然后,详细讨论了每…

门控循环单元GRU

目录 一、GRU提出的背景&#xff1a;1.RNN存在的问题&#xff1a;2.GRU的思想&#xff1a; 二、更新门和重置门&#xff1a;三、GRU网络架构&#xff1a;1.更新门和重置门如何发挥作用&#xff1a;1.1候选隐藏状态H~t&#xff1a;1.2隐藏状态Ht&#xff1a; 2.GRU: 四、训练过程…

当自回归遇到Diffusion

文章目录 Autoregressive Image Generation without Vector Quantization一. 简介1.1 摘要1.1 引言二.相关工作2.1 Sequence Models for Image Generation2.2 Diffusion for Representation Learning2.3 Diffusion for Policy Learning三.方法3.1 重新思考离散值的tokens3.2 Di…

Kotlin OpenCV 图像图像50 Haar 级联分类器模型

Kotlin OpenCV 图像图像50 Haar 级联分类器模型 1 OpenCV Haar 级联分类器模型2 Kotlin OpenCV Haar 测试代码 1 OpenCV Haar 级联分类器模型 Haar级联分类器是一种用于对象检测&#xff08;如人脸检测&#xff09;的机器学习算法。它由Paul Viola和Michael Jones在2001年提出…

conda环境pip 安装Tensorflow-gpu 2.10.2提示nbconvert 的包依赖冲突

问题如下&#xff1a; ERROR: pip’s dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts. nbconvert 7.16.4 requires beautifulsoup4, which is not inst…

DETR论文详解

文章目录 前言一、DETR理论二、模型架构1. CNN2. Transformer3. FFN 三、损失函数四、代码实现总结 前言 DETR是Facebook团队在2020年提出的一篇论文&#xff0c;名字叫做《End-to-End Object Detection with Transformers》端到端的基于Transformers的目标检测&#xff0c;DET…

数仓入门:数据分析模型、数仓建模、离线实时数仓、Lambda、Kappa、湖仓一体

往期推荐 大数据HBase图文简介-CSDN博客 数仓分层ODS、DWD、DWM、DWS、DIM、DM、ADS-CSDN博客 数仓常见名词解析和名词之间的关系-CSDN博客 目录 0. 前言 0.1 浅谈维度建模 0.2 数据分析模型 1. 何为数据仓库 1.1 为什么不直接用业务平台的数据而要建设数仓&#xff1f; …

ChatGPT能代替网络作家吗?

最强AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频百万播放量https://aitools.jurilu.com/ 当然可以&#xff01;只要你玩写作AI玩得6&#xff0c;甚至可以达到某些大神的水平&#xff01; 看看大神、小白、AI输出内容的区…

重塑企业知识库:AI搜索的深度应用与变革

在数字化浪潮的推动下&#xff0c;企业知识库已成为企业智慧的核心载体。而AI搜索技术的融入&#xff0c;让海量信息瞬间变得井然有序&#xff0c;触手可及。它不仅革新了传统的搜索方式&#xff0c;更开启了企业知识管理的新纪元&#xff0c;引领着企业向更加智能化、高效化的…

【人工智能】FPGA实现人工智能算法硬件加速学习笔记

一. FPGA的优势 FPGA拥有高度的重配置性和并行处理能力,能够同时处理多个运算单元和多个数据并行操作。FPGA与卷积神经网络(CNN)的结合,有助于提升CNN的部署效率和性能。由于FPGA功耗很低的特性进一步增强了其吸引力。此外,FPGA可以根据具体算法需求量身打造硬件加速器。针对动…

[CR]厚云填补_SEGDNet

Structure-transferring edge-enhanced grid dehazing network Abstract 在过去的二十年里&#xff0c;图像去雾问题在计算机视觉界受到了极大的关注。在雾霾条件下&#xff0c;由于空气中水汽和粉尘颗粒的散射&#xff0c;图像的清晰度严重降低&#xff0c;使得许多计算机视觉…

鸿蒙媒体开发【基于AVCodec能力的视频编解码】音频和视频

基于AVCodec能力的视频编解码 介绍 本实例基于AVCodec能力&#xff0c;提供基于视频编解码的视频播放和录制的功能。 视频播放的主要流程是将视频文件通过解封装->解码->送显/播放。视频录制的主要流程是相机采集->编码->封装成mp4文件。 播放支持的原子能力规…

【从0到1进阶Redis】Jedis 操作 Redis

笔记内容来自B站博主《遇见狂神说》&#xff1a;Redis视频链接 Jedis 是一个用于 Java 的 Redis 客户端库&#xff0c;它提供了一组 API 用于与 Redis 数据库进行交互。Redis 是一个高性能的键值存储数据库&#xff0c;广泛用于缓存、消息队列等场景。Jedis 使得 Java 开发者能…

图欧科技-IMYAI智能助手24年5月~7月更新日志大汇总

上一篇推文盘点了我们图欧科技团队近一年来的更新日志&#xff0c;可以说是跟随着人工智能时代的发展&#xff0c;我们的IMYAI也丝毫不落后于这场时代的浪潮&#xff01;近三个月以来&#xff0c;我们的更新频率直线上升&#xff0c;现在我们AI网站已经成为一个集GPT、Claude、…

《学会 SpringMVC 系列 · 消息转换器 MessageConverters》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

Inno Setup 安装界面、卸载界面+美化

Inno Setup Inno Setup用Delphi写成&#xff0c;其官方网站同时也提供源程序免费下载。它虽不能与Installshield这类恐龙级的安装制作软件相比&#xff0c;但也当之无愧算是后起之秀。Inno Setup是一个免费的安装制作软件&#xff0c;小巧、简便、精美是其最大特点&#xff0c;…

arduino程序—模拟输出(基础知识)

arduino程序—模拟输出&#xff08;基础知识&#xff09; 1-25 模拟输出1-analogWrite电路效果演示模拟输出analog output复合运算符示例程序Analogwrite&#xff08;&#xff09; 1-26 模拟输出2-PWMPWM概念&#xff08;极其重要&#xff09; 1-27 模拟输出3-for电路效果演示程…

【Verilog-CBB】开发与验证(2)——单比特信号CDC同步器

引言 多时钟域的设计中&#xff0c;CDC处理的场景还是蛮多的。单比特信号在CDC时&#xff0c;为保证信号采样的安全性&#xff0c;降低亚稳态&#xff0c;必须要对信号做同步处理。CDC从时钟的快慢关系来说分为两种case&#xff1a;快到慢、慢到快。对于脉冲型的控制信号&…

『C++实战项目 负载均衡式在线OJ』一、项目介绍与效果展示(持续更新)

文章目录 一、项目介绍二、开发环境三、第三方库四、相关技术五、项目整体框架代码目录框架 代码仓库连接 点击这里✈ 一、项目介绍 本项目是实现一个仿 leetcode 的 OJ (Online-Judge&#xff09;系统。更准确的说应该称之为leetcode 的裁剪版。因为本项目只实现了leetcode中…