头脑风暴之约瑟夫环问题

news2024/11/16 9:27:46
一 问题的引入

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

  • 现有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 的人直接删除就Ok
            pre->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 的人直接删除就Ok
            pre->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 的人直接删除就Ok
            pre->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.coloradmin.cn/o/1121689.html

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

相关文章

阶段七-Day01-Spring01

一、Spring框架介绍 1. 介绍 Spring Framework是由Spring团队研发的模块化、轻量级开源框架。其主要目的是为了简化项目开发。 Spring Framework前身是interface21&#xff0c;由Rod Johnson于2002年研发&#xff0c;主要是为了不使用EJB下依然能够构建高质量Java EE项目。E…

Ubuntu下 u2net tensorrt模型部署

TensorRT系列之 Windows10下yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov7 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov6 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov5 tensorrt模型加速…

浅析人脸活体检测技术的功能及几种分类

在日常生活工作中&#xff0c;出现了人脸验证、人脸支付、人脸乘梯、人脸门禁等等常见的应用场景。这说明人脸识别技术已经在门禁安防、金融行业、教育医疗等领域被广泛地应用&#xff0c;人脸识别技术的高速发展与应用同时也出现不少质疑。其中之一就是人脸识别很容易被照片、…

DDOS攻击的有效防护方式有哪些?

DDoS攻击简介&#xff1a; DDoS攻击&#xff0c;即分布式拒绝服务攻击&#xff08;Distributed Denial of Service&#xff09;&#xff0c;是一种网络攻击&#xff0c;旨在通过向目标服务器发送大量恶意请求&#xff0c;使服务器资源耗尽&#xff0c;无法满足合法用户的需求&a…

KubeSphere安装KubeEdge

1. kubesphere安装请参考博客 2. 配置master节点 控制台->平台管理->集群管理->自定义CRD&#xff0c;搜索​​clusterconfiguration​​&#xff0c;查看详情&#xff0c;在资源列表中&#xff0c;点击 ​​ks-installer​​ 右侧的图标&#xff0c;然后选择编辑配…

一文带你彻底弄懂ZGC

1 推荐的文章 1.1 必看 干掉1ms以内的Java垃圾收集器ZGC到底是个什么东西&#xff1f; 1.2 选看 ZGC有什么缺点? 2 疑问【皆来自上面两篇文章】 2.1 什么使得用户线程工作的同时&#xff0c;让垃圾收集器可以回收垃圾-读写屏障 ZGC (Z Garbage Collector) 和读写屏障: …

【瑞吉外卖部分功能补充】

瑞吉外卖部分功能补充 菜品的启售和停售 在浏览器控制台点击对应功能后可以看到前端发送的请求是&#xff1a;http://localhost:9999/dish/status/1?ids1413342036832100354&#xff0c;请求方式为POST。 接收到前端参数后&#xff0c;进行controller层代码补全&#xff0c…

简单说明反射和new的区别和反射的使用代码展示

目录 1.反射的认识 2.反射和new的区别 3.反射的使用代码展示 4.反射优点和缺点 1.反射的认识 反射是Java语言的一种机制&#xff0c;它允许程序在运行时检查和操作类、方法、字段等信息&#xff0c;而不需要提前知道它们的具体定义。通过反射&#xff0c;我们可以在运行时动…

直接插入排序——希尔排序

排序——先写单个——再衍生到整体 单个插入排序——在插入前数组里面的数是有序的&#xff0c;然后来了一个数据&#xff0c;就要用这个数组从后往前和这个数比较&#xff0c; 整体的话就是&#xff0c;end从0开始&#xff0c;循环n-1次 void TnsertSort(int* a,int n) {in…

QML之Repeater 控件使用

Repeater 控件是 重复作用 根据 model中的index 数量进行重复 废话不说 直接看如何用 当model 为数字时 Rectangle{height: 1200width: 500visible: trueanchors.fill: parentColumn{spacing: 20Repeater{model: 10delegate: Rectangle{width: 60height: 20color: index%2 …

VulnHub ch4inrulz: 1.0.1

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏…

【网络编程】应用层——HTTP协议

文章目录 一、HTTP协议简介二、认识URL三、HTTP协议格式1. HTTP请求协议格式2. HTTP响应协议格式 三、构建HTTP请求和响应四、HTTP的方法五、HTTP的状态码六、HTTP常见的Header七、Cookie和Session 一、HTTP协议简介 HTTP 协议 是 Hyper Text Transfer Protocol&#xff08;超文…

苹果ios打包出来的ipa应用APP怎么不能安装?多种安装不上的原因排查

亲爱的同学们&#xff0c;非常高兴能和同学们一起探讨关于苹果应用安装失败的问题。作为一个开发者&#xff0c;我们很可能会遇到这样的情况&#xff1a;开发好一个应用&#xff0c;兴致勃勃地想把它运行到手机上去测试&#xff0c;结果发现安装失败了。而此时&#xff0c;定位…

【2023_10_22计算机热点知识分享】:人工智能

最近计算机领域的热点话题之一是人工智能的发展。人工智能是一种能够模拟人类智能的技术&#xff0c;它可以通过机器学习、深度学习、自然语言处理等技术&#xff0c;实现语音识别、图像识别、自然语言处理等智能化的功能。人工智能技术的发展&#xff0c;正在深刻地改变着人类…

Docker概述、部署、镜像与容器管理

Docker概述、部署、镜像与容器操作 一、Docker是什么&#xff1f;1.1、Docker介绍1.2、Docker的设计宗旨1.3、容器运行条件1.4、容器与虚拟机的区别1.5、Docker核心概念1.5.1、镜像1.5.2、容器1.5.3、仓库 二、Docker部署三、Docker 镜像管理3.1、搜索镜像3.2、查看仓库中有哪些…

01-JVM 内存结构

JVM 内存结构 Java 虚拟机的内存空间分为 5 个部分&#xff1a; 程序计数器Java 虚拟机栈本地方法栈堆方法区 JDK 1.8 同 JDK 1.7 比&#xff0c;最大的差别就是&#xff1a;元数据区取代了永久代。元空间的本质和永久代类似&#xff0c;都是对 JVM 规范中方法区的实现。不过…

Redis --- 安装教程

Redis--- 特性&#xff0c;使用场景&#xff0c;安装 安装教程在Centos7.6下安装Redis5 特性在内存中存储数据可编程的扩展能力持久化集群高可用快速 应用场景实时数据存储作为缓存或者Session存储消息队列 安装教程 在Centos7.6下安装Redis5 1.安装scl源 yum install cento…

云原生微服务 第十章 Spring Cloud Alibaba 之 Nacos discovery

系列文章目录 第一章 Java线程池技术应用 第二章 CountDownLatch和Semaphone的应用 第三章 Spring Cloud 简介 第四章 Spring Cloud Netflix 之 Eureka 第五章 Spring Cloud Netflix 之 Ribbon 第六章 Spring Cloud 之 OpenFeign 第七章 Spring Cloud 之 GateWay 第八章 Sprin…

STM32F4_网络通信(网口)

前言 STM32F4开发板上自带了网口。可以通过开发板自带的网口和LWIP实现&#xff1a;TCP服务器、TCP客服端、UDP以及WEB服务器等四个功能。 1. STM32 以太网简介 STM32F4 芯片自带以太网模块&#xff0c;该模块包括带有专用 DMA 控制器的 MAC 802.3&#xff08;介质访问控制&am…

文心一言 VS 讯飞星火 VS chatgpt (118)-- 算法导论10.3 3题

三、用go语言&#xff0c;在ALLOCATE-OBJECT和 FREE-OBJECT过程的实现中&#xff0c;为什么不需要设置或重置对象的 prev 属性呢? 文心一言&#xff1a; 在 Go 语言中&#xff0c;ALLOCATE-OBJECT 和 FREE-OBJECT 过程的实现通常不需要显式地设置或重置对象的 prev 属性。这…