C语言:约瑟夫环问题详解

news2024/12/27 13:14:59

前言
哈喽,宝子们!本期为大家带来一道C语言循环链表的经典算法题(约瑟夫环)。

目录

  • 1.什么是约瑟夫环
  • 2.解决方案思路
  • 3.创建链表头结点
  • 4.创建循环链表
  • 5.删除链表
  • 6.完整代码实现

1.什么是约瑟夫环

据说著名历史学家Josephus有过以下的故事:在罗马人占领乔塔帕特后,39个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被人抓到,于是决定了一个自杀方式,41个人拼成一个圆圈,由第一个人开始报数,每报数到第三人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。
然而Josephus和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
这道题的原理也是一样的,来看看这道题长什么样吧。
描述:
编号为 1 到 n 的 n 个人围成一圈。从编号为 1 的人开始报数,报到 m 的人离开。下一个人继续从 1 开始报数。
n - 1 轮结束以后,只剩下一个人,问最后留下的这个人编号是多少?
示例1:
输入:5, 2
返回值:3
说明:
开始5个人 1,2,3,4,5 ,从1开始报数,1->1,2->2编号为2的人离开。
1,3,4,5,从3开始报数,3->1,4->2编号为4的人离开。
1,3,5,从5开始报数,5->1,1->2编号为1的人离开。
3,5,从3开始报数,3->1,5->2编号为5的人离开。
最后留下人的编号是3。

2.解决方案思路

既然是循环的报数,那我们就可以用我们所学过的单链表来解决这道题。

  1. 那假设我们有n个人,就要创建n个节点,首先创建一个节点,然后同时用两个指针指向这个节点,这个节点既是头指针head,也是尾指针ptail
  2. 然后把这个创建的过程用一个函数封装起来,调用函数来创建剩下的几个节点,每次调用完就让ptail的next指针指向我们新创建的节点,然后更新ptail指针的位置。
  3. 此时,我们的节点已经全部创建完成了,但是最重要的一步,就是要让我们的链表形成一个环,最后让尾指针的next指针指向我们的head
  4. 接着就是报数的实现需要有循环,报数要用一个计数器count来记录,当count等于m的时候,就要删除当前这个节点,然后更改头指针和尾指针的位置,最后直到头指针指向自己,此时指针里val的值就是最终留下来的值。
    在这里插入图片描述

3.创建链表头结点

//创建头链表
ListNode* ListBuyNode(int x)
{
    ListNode* newhead = (ListNode*)malloc(sizeof(ListNode));
    //动态申请内存失败
    if (newhead == NULL)
    {
        exit(1);
    }
    //申请成功
    newhead->val = x;
    newhead->next = NULL;
    return newhead;
}

4.创建循环链表

//创建带环链表
ListNode* CreateCircle(int n)
{
    //先创建第一个节点
    ListNode* head = ListBuyNode(1);
    ListNode* ptail = head;
    for (int i = 2; i <= n; i++)
    {
        //用尾插的方式把节点连接起来
        ptail->next = ListBuyNode(i);
        ptail = ptail->next;//更新尾节点位置
    }
    //收尾相连,链表成环
    ptail->next = head;
    return ptail;
}

5.删除链表

//当链表中只有一个节点的情况就是循环的终止条件
while (pcur->next != pcur)
{
    if (count == m)
    {
        //销毁pcur节点
        prev->next = pcur->next;
        free(pcur);
        pcur = prev->next;
        count = 1;
    }
    else
    {
        //此时不需要销毁节点
        prev = pcur;
        pcur = pcur->next;
        count++;
    }
}

6.完整代码实现

//定义节点
struct ListNode
{
    int val;
    struct ListNode* next;
};
typedef struct ListNode ListNode;//类型重定义
//创建头链表
ListNode* ListBuyNode(int x)
{
    ListNode* newhead = (ListNode*)malloc(sizeof(ListNode));
    if (newhead == NULL)
    {
        exit(1);
    }
    newhead->val = x;
    newhead->next = NULL;
    return newhead;
}
//创建带环链表
ListNode* CreateCircle(int n)
{
    //先创建第一个节点
    ListNode* head = ListBuyNode(1);
    ListNode* ptail = head;
    for (int i = 2; i <= n; i++)
    {
        ptail->next = ListBuyNode(i);
        ptail = ptail->next;
    }
    //收尾相连,链表成环
    ptail->next = head;
    return ptail;
}
int ysf(int n, int m) 
{
    //1.根据n创建带环链表
    ListNode* prev = CreateCircle(n);//尾指针
    ListNode* pcur = prev->next;//头指针
    int count = 1;
    //当链表中只有一个节点的情况就是循环的终止条件
    while (pcur->next != pcur)
    {
        if (count == m)
        {
            //销毁pcur节点
            prev->next = pcur->next;
            free(pcur);
            pcur = prev->next;
            count = 1;
        }
        else
        {
            //此时不需要销毁节点
            prev = pcur;
            pcur = pcur->next;
            count++;
        }
    }
    //此时剩下的最后一个节点里的值就是要返回的值
    return prev->val;
}
int main()
{
    //测试用例
    int win=ysf(5, 2);
    printf("%d", win);
    return 0;
}

如果对你有所帮助的话,别忘了点赞+关注哟❤️!

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

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

相关文章

Ribbon-负载均衡原理解析(案例)

简介&#xff1a;负载均衡&#xff0c;英文名称为Load Balance&#xff0c;其含义就是指将负载&#xff08;工作任务&#xff09;进行平衡、分摊到多个操作单元上进行运行&#xff0c;例如FTP服务器、Web服务器、企业核心应用服务器和其它主要任务服务器等&#xff0c;从而协同…

MATLAB数据类型和运算符+矩阵创建

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 ✍一、MATLAB数据类型和运算符&#x1f48e;1 MATLAB的数据类型&#x1f339;…

QT常用控件

常用控件 控件概述QWidget 核⼼属性核⼼属性概览enabledgeometrywindowTitlewindowIconwindowOpacitycursorfonttoolTipfocusPolicystyleSheet 按钮类控件Push ButtonRadio ButtionCheck Box 显⽰类控件LabelLCD NumberProgressBarCalendar Widget 输⼊类控件Line EditText Edi…

[尚硅谷 flink] 状态管理 笔记

文章目录 10.1 状态概述10.2 状态分类1&#xff09;托管状态&#xff08;Managed State&#xff09;和原始状态&#xff08;Raw State&#xff09;2&#xff09;算子状态&#xff08;Operator State&#xff09;和按键分区状态&#xff08;Keyed State&#xff09; 10.3 按键分…

【OTA】STM32-OTA升级——持续更新

【OTA】STM32-OTA升级——持续更新 文章目录 前言一、ymodem串口协议1、Ymodem 协议2、PC3、蓝牙4、WIFI云平台 二、UDS车载协议1.UDS协议 总结 前言 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、ymodem串口协议 1、Ymodem 协议 STM32 Ymodem …

React 组件生命周期对比:Class vs. 函数式

在 React 中&#xff0c;Class 组件和函数式组件的生命周期存在一些差异。通过对 React 中 Class 组件和函数式组件的生命周期进行对比&#xff0c;详细探讨了它们在设计哲学、生命周期管理和开发技巧上的异同。全面了解 React 中两种组件类型的生命周期特点&#xff0c;以及如…

10个Python接私活平台,打破职场信息闭塞,告别死工资!

前言 Python是一种简单易学、高效强大的编程语言&#xff0c;正变成越来越多人选择的热门技能。不论你是否有编程基础&#xff0c;在学习Python的道路上&#xff0c;坚持每天投入2小时&#xff0c;你将看到巨大的回报。 学习Python不仅可以为你提供更多就业机会&#xff0c;还…

微信小程序 uniapp+vue.js医疗在线问诊挂号系统4oy17

预约挂号系统的逐渐发展&#xff0c;进一步方便了广大用户&#xff0c;使其可以更方便、快捷地预约挂号&#xff0c;并且也有效地防止号贩子“倒号”&#xff0c;使用户预约挂号更公平&#xff0c;然而现有预约挂号系统或多或少有所欠缺 小程序前端框架&#xff1a;uniapp 小程…

【问题解决】ubuntu安装新版vscode报code-insiders相关错误

问题 目前 vscode官网 最新的包为 insiders_1.89.0-1712297812_amd64.deb &#xff0c;双击或者使用sudo dpkg -i code-insiders_1.89.0-1712297812_amd64.deb安装后报错&#xff0c;执行其他命令也报错。 安装环境&#xff1a;ubuntu18.04 dpkg: 处理软件包 code-insiders (…

现在租一个服务器多少一个月啊?

现在租一个服务器多少一个月&#xff1f;优惠价格低至3.8元1个月&#xff0c;租用一个月云服务器收费价格表&#xff1a;阿里云和腾讯云2核2G3M服务器优惠价格61元一年&#xff0c;折合一个月5元&#xff0c;京东云轻量云主机5.8元一个月&#xff0c;华为云服务器优惠价格3.8元…

同态加密:重塑数据隐私与安全的未来

同态加密技术是当今信息安全领域的一个重要研究方向&#xff0c;它允许在加密数据上直接进行计算&#xff0c;而无需将数据解密。这种加密方式对于保护数据隐私和增强云计算安全具有重要意义。在这篇文章中&#xff0c;我们将深入探讨同态加密的基本概念、技术特点、应用场景以…

每日一题---OJ题: 返回倒数第 k 个节点

片头 嗨! 小伙伴们,大家好! 今天我们来一起学习这道OJ题---返回倒数第k个结点,准备好了吗? 我们开始咯! 比如: 总共有5个结点,分别为 1->2->3->4->5 , 找倒数第一个结点,也就是"5" 题目很容易理解,我们先提供第一种思路 思路一: 假设链表长度为 n ,…

大数据实训进行时:数据标注项目

数据标注项目 培训目的 让同学们先熟悉理论知识&#xff0c;如&#xff1a;识别障碍物是否满足拉框的要求&#xff0c;如何进行拉框&#xff1b;熟悉标注操作&#xff0c;培养出能够进入正式项目的人员 培训地点 理论&#xff1a;学术报告厅、阶梯教室 实操&#xff1a;1实…

LeetCode-32. 最长有效括号【栈 字符串 动态规划】

LeetCode-32. 最长有效括号【栈 字符串 动态规划】 题目描述&#xff1a;解题思路一&#xff1a;辅助栈解题思路二&#xff1a;动态规划解题思路三&#xff1a;0 题目描述&#xff1a; 给你一个只包含 ‘(’ 和 ‘)’ 的字符串&#xff0c;找出最长有效&#xff08;格式正确且…

Redis的RDB文件

Redis持久化 Redis是操作内存的&#xff0c;所以是内存数据库&#xff0c;断电即失&#xff0c;所以需要持久化 RDB 文件名:dump.rdb # The filename where to dump the DB dbfilename dump.rdb在指定时间间隔内&#xff0c;将内存中的数据&#xff0c;集体快照写入磁盘内&…

linux如何使 CPU使用率保持在指定百分比?

目录 方法1&#xff1a;&#xff08;固定在100%&#xff09; 方法2&#xff1a;&#xff08;可以指定0~100%&#xff09; 方法3&#xff1a;使用ChaosBlade工具&#xff08;0~100%&#xff09; 方法1&#xff1a;&#xff08;固定在100%&#xff09; for i in seq 1 $(cat /pro…

Leetcode算法训练日记 | day25

一、组合总和Ⅲ 1.题目 Leetcode&#xff1a;第 216 题 找出所有相加之和为 n 的 k 个数的组合&#xff0c;且满足下列条件&#xff1a; 只使用数字1到9每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次&#xff0c;组合可以以任何顺…

gemini1.5 API调用

https://ai.google.dev/pricing?hlzh-cn 查询可用的model https://generativelanguage.googleapis.com/v1beta/models?keyxxx 使用postman调用 https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro-latest:generateContent?keyxxx https://ai.google…

数学基础:矩阵

来自: https://www.shuxuele.com/algebra/matrix-determinant.html 一、矩阵的行列式 二、矩阵简单知识 三、矩阵乘法 四、单位矩阵 五、逆矩阵一&#xff1a;简单2阶矩阵求法 六、逆矩阵二&#xff1a;3、4阶逆矩阵求法 6.1 求余子式矩阵 6.2 求代数余子式矩阵 6.3 求伴随矩阵…

练习题(2024/4/13)

1长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 连续 子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其长度。如果不存在符合条件的子数组&#xff0c;返回 0 。 示例 1&am…