头脑风暴之约瑟夫环问题

一 问题的引入

约瑟夫问题的源头完全可以命名为“自杀游戏”。本着和谐友爱和追求本质的目的,可以把问题描述如下:

  • 现有n个人围成一桌坐下,编号从1到n,从编号为1的人开始报数。
  • 报数也从1开始,报到m人离席,从离席者的下一位在座成员开始,继续从1开始报数。
  • 复现这个过程(各成员的离席次序),或者求最后一个在座的成员编号。

二 思路的讲解

1. 想必我们看到这个游戏场景,再结合链表相关的知识,我们也就大概有了一个方向了吧~~~

没错,解决约瑟夫问题的关键就是创建一个带环链表

 2.当我们链表创建好之后,就是考虑如何讲单链表转换成带头循环链表

是滴,就是将我们的链表的尾结点指向我们的头节点即可

ptail->next = phead;

 对应代码如下:

ListNode* CreatList(int x)//链表创建
{ListNode* phead = ListBuyNode(1);//注意是从数据1开始为每一个人创建结点ListNode* ptail = phead;//注意当链表只有一个数据时,头节点也是尾结点//来到这里说明头节点已经创建好,下面就需要进行尾插即可,尾插之前需找到前面的结点for (int i = 2; i <= x; i++){ListNode* node = ListBuyNode(i);ptail->next = node;ptail = ptail->next;//尾结点时刻更新}//以上只是单链表创建好了,下面需把他变成单向循环链表ptail->next = phead;return ptail;//返回尾结点即可,有了尾结点可以直接找到头节点,若是返回头节点,需要遍历才可以找到尾结点}

3.以上我们把前期准备工作已经做好了,接下来我们开始约瑟夫游戏

其实就是一个删除结点的问题

注意我们这里不能直接删除结点

1.)删除结点之前我们需要先找到这个结点的前一个结点,也就是pre这个结点

2.)其次就是找到这个结点的后一个结点,即pcur->next;

3.)最最最重要的是,我们在删除这个结点之后,不要忘了让下一个人重新报数

草图如下:

 代码如下:

 接下来重复以上操作即可,也就是对应代码里面的循环,具体详见代码:

    while (pcur->next != pcur){if (count == m){//报到为m 的人直接删除就Okpre->next = pcur->next;free(pcur);//此时pcur是个野指针pcur = pre->next;count = 1;//删除结点后,别忘了count 是从1重新开始报数}else{pre = pcur;//pcur移动之前,需让pre 来保存pcur位置,pcur = pcur->next;count++;//注意别忘了要报数}}

相信各位对以上的分析应该有了自己的理解了吧~~~

 

对于IO答题方式:完整代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
#include<malloc.h>int yef(int x, int y);
typedef struct ListNode
{int val;//数据域struct ListNode* next;//指针域
}ListNode;//重命名
ListNode* ListBuyNode(int x)//创建结点
{ListNode* node = (ListNode*)malloc(sizeof(ListNode));if (node == NULL)//会存在开辟失败{perror("malloc fail\n");return 5;}//空间开辟成功node->val = x;node->next = NULL;return node;
}
ListNode* CreatList(int x)//链表创建
{ListNode* phead = ListBuyNode(1);//注意是从数据1开始为每一个人创建结点ListNode* ptail = phead;//注意当链表只有一个数据时,头节点也是尾结点//来到这里说明头节点已经创建好,下面就需要进行尾插即可,尾插之前需找到前面的结点for (int i = 2; i <= x; i++){ListNode* node = ListBuyNode(i);ptail->next = node;ptail = ptail->next;//尾结点时刻更新}//以上只是单链表创建好了,下面需把他变成单向循环链表ptail->next = phead;return ptail;//返回尾结点即可,有了尾结点可以直接找到头节点,若是返回头节点,需要遍历才可以找到尾结点}
int ysf(int n, int m) {ListNode* ptail = CreatList(n);//为1~n个人创建单循环链表,注意链表创建返回的就是尾结点//开始游戏,涉及到删除结点,注意不能直接删除,删除前需要先找到对应的前一个结点和后一个结点ListNode* pcur = ptail->next;//游戏是从第一个人开始的ListNode* pre = ptail;//当前节点的前一个结点int count = 1;//就是一个报数器,注意是从1开始的而不是0开始的,因为游戏是从第一个人开始while (pcur->next != pcur){if (count == m){//报到为m 的人直接删除就Okpre->next = pcur->next;free(pcur);//此时pcur是个野指针pcur = pre->next;count = 1;//删除结点后,别忘了count 是从1重新开始报数}else{pre = pcur;//pcur移动之前,需让pre 来保存pcur位置,pcur = pcur->next;count++;//注意别忘了要报数}}//此时只剩一个结点return pcur->val;
}
int main()
{int ret =  ysf(43,9001);printf("%d", ret);return 0;
}

对于OJ的答题方式,完整代码如下

//解答思路 首先创建一个带头单向循环链表  其次删除这个链表的结点,注意不能直接删除,要找到删除此节点的前一个和后一个结点typedef struct ListNode ListNode;//重命名ListNode* ListBuyNode(int x)//创建结点{ListNode* node = (ListNode*)malloc(sizeof(ListNode));if(node == NULL)//会存在开辟失败{perror("malloc fail\n");}//空间开辟成功node->val = x;node->next = NULL;return node;}ListNode* CreatList(int x)//链表创建{ListNode* phead = ListBuyNode(1);//注意是从数据1开始为每一个人创建结点ListNode* ptail = phead;//注意当链表只有一个数据时,头节点也是尾结点//来到这里说明头节点已经创建好,下面就需要进行尾插即可,尾插之前需找到前面的结点for(int i = 2;i <= x;i++){ListNode* node = ListBuyNode(i);ptail->next = node;ptail = ptail->next;//尾结点时刻更新}//以上只是单链表创建好了,下面需把他变成单向循环链表ptail->next = phead;return ptail;//返回尾结点即可,有了尾结点可以直接找到头节点,若是返回头节点,需要遍历才可以找到尾结点}
int ysf(int n, int m ) {ListNode* pre = CreatList(n);//为1~n个人创建单循环链表,注意链表创建返回的就是尾结点//开始游戏,涉及到删除结点,注意不能直接删除,删除前需要先找到对应的前一个结点和后一个结点ListNode* pcur = pre->next;//游戏是从第一个人开始的int count = 1;//就是一个报数器,注意是从1开始的而不是0开始的,因为游戏是从第一个人开始while(pcur->next != pcur){if(count == m){//报到为m 的人直接删除就Okpre->next  = pcur->next;free(pcur);//此时pcur是个野指针pcur = pre->next;count = 1;//删除结点后,别忘了count 是从1重新开始报数}else {pre = pcur;//pcur移动之前,需让pre 来保存pcur位置,pcur = pcur->next;count++;//注意别忘了要报数}}//此时只剩一个结点return pcur->val;}

 各位大佬都已经来这里了,若是觉得还不错,咱点个赞,互关一下呗,蟹蟹大家了,小生有礼了。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

重生奇迹mu宠物带来不一样的体验

重生奇迹mu宠物有什么作用&#xff1f; 全新版本中更是推出了各种宠物&#xff0c;在玩游戏时还可以带着宠物&#xff0c;一起疯狂的刷怪等等&#xff0c;可以为玩家带来非常不错的游戏体验&#xff0c;那么下面就来给大家说说各种宠物适合做什么事情。 1、强化恶魔适合刷怪 …

爱创科技携手洽洽食品,探索渠道数字化最优解!

坚果的下半场&#xff0c;是从吃到喝。 消费升级大潮下&#xff0c;健康养生理念逐渐深入人心。以“天然健康”为核心的食品新消费潮流正加速形成&#xff0c;一个个打着“美味与营养”黄金设定的品类风口正被不断创建&#xff0c;其中人气有增无减的当属植物基饮品。据相关报告…

HarmonyOS鸿蒙原生应用开发设计- HarmonyOS Sans 字体

HarmonyOS设计文档中&#xff0c;为大家提供了独特的字体&#xff0c;开发者可以根据需要直接引用。 开发者直接使用官方提供的字体内容&#xff0c;既可以符合HarmonyOS原生应用的开发上架运营规范&#xff0c;又可以防止使用别人的字体侵权意外情况等&#xff0c;减少自主创…

【Linux驱动】Linux设备树(二)—— 添加设备树节点

了解了设备树的基本语法以后&#xff0c;就可以试着自己手动添加一个节点了&#xff0c;添加完节点以后&#xff0c;需要重新编译生成 .dtb 文件&#xff0c;然后保存到uboot的加载目录下。 目录 1、查看绑定信息文档 2、添加设备树节点 3、编译设备树文件(.dtb) 4、替换设…

JAVA基础(JAVA SE)学习笔记(七)面向对象编程(进阶)

前言 1. 学习视频&#xff1a; 尚硅谷Java零基础全套视频教程(宋红康2023版&#xff0c;java入门自学必备)_哔哩哔哩_bilibili 2023最新Java学习路线 - 哔哩哔哩 第二阶段&#xff1a;Java面向对象编程 6.面向对象编程&#xff08;基础&#xff09; 7.面向对象编程&…

IP协议(下)

目录 一、IP分片 1.为什么需要IP分片 2.IP报头信息 二、分片的组装 1.接收方怎么知道一个报文被分片了 2.同一个报文的分片怎么全部识别出来的 3.报文如何排序&#xff0c;如何得知报文有没有收全 4.怎么将各分片正确组装 5.怎么确定合成的报文是正确的 6.总结 三、…

SSM - Springboot - MyBatis-Plus 全栈体系(三十五)

第八章 项目实战 四、后台功能开发 2. 首页模块开发 2.1 查询首页分类 2.1.1 需求描述 进入新闻首页,查询所有分类并动态展示新闻类别栏位 2.1.2 接口描述 url 地址&#xff1a;portal/findAllTypes 请求方式&#xff1a;get 请求参数&#xff1a;无 响应数据&#xff…

【Python · PyTorch】数据基础

数据基础 1. 数据操作1.1 入门1.2 运算符1.3 广播机制1.4 索引和切片1.5 节省内存1.6 转化为其他Python对象 2. 数据预处理2.1 读取数据集2.2 处理缺失值2.3 转换为张量格式 本文介绍了PyTorch数据基础&#xff0c;Python版本3.9.0&#xff0c;代码于Jupyter Lab中运行&#xf…

红队专题-从零开始VC++C/S远程控制软件RAT-MFC-[5]客户端与服务端连接

红队专题 招募六边形战士队员端操作系统SystemInfo类获取系统信息发送系统信息头文件声明头文件调用 未找到来自 OleAcc.dll 的导入LINK 招募六边形战士队员 一起学习 代码审计、安全开发、web攻防、逆向等。。。 私信联系 端 发送连接->进入主线程->返回socket->…

[SWPUCTF 2023 秋季新生赛] web题解

文章目录 colorful_snakeNSS_HTTP_CHEKER一键连接!ez_talkPingpingpingUnS3rialize查查needIf_elseRCE-PLUSbackup colorful_snake 打开题目&#xff0c;查看js源码 直接搜flag 把那三行代码复制到控制器&#xff0c;得到flag NSS_HTTP_CHEKER 都是http请求基本知识 抓包按照…

【保姆级教程】:docker搭建MongoDB三节点副本集

容器可以理解为一个进程&#xff0c;镜像是把环境&#xff0c;组件等都配置好&#xff0c;运行成容器的&#xff0c;容器里面运行服务&#xff0c;也可以说是一个进程。镜像是模板&#xff0c;镜像是实例。 一个镜像可以创建多个实例。也就是多个容器&#xff0c;容器之间相互…

驱动作业10.23

现象 test.c #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include "head.h"in…

TCP/IP(二十)TCP 实战抓包分析(四)TCP 第二次握手 SYN、ACK 丢包

一 实验二&#xff1a;TCP 第二次握手 SYN、ACK 丢包 重点&#xff1a; 通过设置 tcp_synack_retries 和 tcp_syn_retries内核参数,观察丢包的现象 ① 实验环境 iptables -t filter -I INPUT -s 172.25.2.100 -j DROPtcpdump -nni ens3 tcp and host 172.25.2.100 and por…

蛇口街道小区长者服务示范点 ——在家门口“乐享晚年”

2023年9月28日&#xff0c;深圳市南山区蛇口街道创建健康街道行动之“老年肌少症免费筛查”项目走进了海昌社区&#xff0c;为数十位长者开展了系统筛查。在家门口就能够享受到由蛇口医院康复科医生提供的专业服务&#xff0c;这对于小区的老人们来说还是第一次。自今年7月以来…

python之代理ip的配置与调试方法详解

代理IP在Python中是一种强大的工具&#xff0c;它可以用于隐藏真实IP地址、绕过访问限制、提高数据爬取和网络请求的效率等。下面将详细介绍Python中代理IP的配置与调试方法&#xff0c;帮助您更好地理解和应用代理IP。 1. 选择合适的代理IP 在使用代理IP之前&#xff0c;需要…

自然语言处理---Transformer构建语言模型

语言模型概述 以一个符合语言规律的序列为输入&#xff0c;模型将利用序列间关系等特征&#xff0c;输出一个在所有词汇上的概率分布&#xff0c;这样的模型称为语言模型。 # 语言模型的训练语料一般来自于文章&#xff0c;对应的源文本和目标文本形如: src1 "I can do&…

硬件服务器更换IPMI

重启按F2进入Biso界面 然后进入Server Management界面&#xff0c;选择BMC LAN Configuration

excel怎么固定前几行前几列不滚动?

在Excel中&#xff0c;如果你想固定前几行或前几列不滚动&#xff0c;可以通过以下几种方法来实现。详细的介绍如下&#xff1a; **固定前几行不滚动&#xff1a;** 1. 选择需要固定的行数。例如&#xff0c;如果你想要固定前3行&#xff0c;应该选中第4行的单元格。 2. 在E…

Markdown语法详解

文章目录 [toc] 一、简介二、样式1. 标题2. 字体3. 引用4. 分割线5. 图片6. 超链接7. 列表8. 表格9. 代码 一、简介 以前写学习文档常用的软件都是Word或者CSDN自带的编辑器&#xff0c;但Word用起来不太灵活&#xff0c;而CSDN自带编辑器又感觉逼格不够&#xff08;主要原因&…

c语言练习91:合并两个有序链表

合并两个有序链表 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 代码1&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/typedef struct ListNode ListNode; struct Li…