2种方法求解约瑟夫环问题

用循环队列求解约瑟夫环问题 用循环队列求解约瑟夫环问题 大家好,这次我们来求解求解约瑟夫环问题,并对比用循环队列和用普通形式求解之间的不同之处。也欢迎各位大佬指正。 目录如下可快速查阅问题描述循环队列求解算法描述程序清单运行结果普通形式求解算法描述程序清单运行结果对比分析 问题描述 设有n个人站成一圈,其编号为1~n。从编号为1的人开始按顺时针方向1、2……循环报数,数到m的人出列,然后从出列者的下一个人重新开始报数,数到m... 阅读详情
 

问题:n个人围成一圈缝m报数,数到m的出列,后面的人开始继续从1开始,数到m的出列,问最后剩下的一个人的序号是多少。

 

一.循环单链表求解

//循环队列求解约瑟夫问题
#include<stdio.h>
#include<stdlib.h>

typedef struct student
{
	int data;
	struct student *next;
}Node;

void Delete(Node *p)//(1)
{
	Node *q;
	int j=1;
	q=p->next;
	p->next=q->next;
	free(q);
}

Node *Create(int n)
{
	Node *head=(Node *)malloc(sizeof(Node));
	Node *s, *r;
	r=head;
	for(int i=1; i<=n; i++)
	{
		s=(Node *)malloc(sizeof(Node));
		s->data=i;
		r->next=s;
		r=s;
	}
	r->next=head->next;//(2)
	return head;
}

void Josephus(Node *head, int n, int m)//约瑟夫环主题函数
{
	Node *p;
	p=head->next;
	int k=0;
	while(p!=p->next)//如果p==p->next了,说明只有一个节点了,目标达成。
	{
		k++;
		if(k==m-1)//(3)
		{
			k=0;
			Delete(p);
		}
		p=p->next;
	}
	printf("\n%d is left\n",p->data);
}

int main()
{
	Node *head;
	int n, m;
	printf("Input n and m\n");
	scanf("%d%d",&n,&m);//n是元素个数,m是到缝m报数,m必须大于
	head=Create(n);
	Josephus(head, n,m);
	system("pause");

	return 0;
}
注意://(1)这个函数与之前的队列各种操作合集里面的Del不一样。那个个参数,一个头结点一个待删除节点的序号i。先找到第i-1个节点。然后删除。这个不太一样,仅仅是一个参数,而且是传递是某个指针。注意,由于单链表无法向前寻找,所以我传递的节点的指针过来之后,只能删除这个节点的后面一个节点,所以无法删除传递节点,只能删除传递节点的后一个节点。所以要在后面的函数体里面稍微处理一下。
//(2)此处灵活处理了一下,还是保持带头节点的风范--头结点head里面不存值,head->next开始存值。但是考虑到在回环的时候因为head里面不存值,还得每次都判断,不方便,就不把尾节点的next指向head了,而是尾节点的next直接指向head的next。这样就不用每次都判断了,反正head也没啥用。
//(3)这里最关键,按照数组方法,这里是k==m做判断,因为k从开始,第一个节点的时候k=1,然后依次递增。当增到m的时候,说明到了m个,开始报数,然后按理说改删除这个节点,而此时,p也正好移动到了m号节点。但是由于Delete函数删除的是所给节点的后续节点。所以此处判断就要改为k==m-1,到m-1的时候,p也指向m-1的节点,这时把p传给Delete就可以删除第m节点了。

运行结果如下:

二.数组方式求解

//数组求解约瑟夫问题
#include<stdio.h>
#include<stdlib.h>

#define nmax 150
int main()
{
	int  i, k, out_cnt, n, m, num[nmax], *p;
	printf("please input n and m:\n");
	scanf("%d%d",&n, &m);
	p=num;
	for(i=0;i<n;i++)
	{
		*(p+i)=i+1;
	}
	i=0;
	k=0;
	out_cnt=0;//out_cnt是用来计数出列个数的,一共出列n-1个,所以下面的while循环以out_cnt<n-1为边界条件,out_num从0-n-2一共n-1个,出列了n-1也就是只剩个在列了
	while(out_cnt<n-1)
	{
		if(*(p+i)!=0)
		{
			k++;
		}
		if(k==m)
		{
			*(p+i)=0;//链表方法中出列元素删除节点,这里无法删除,采取置的方法。
			k=0;
			out_cnt++;//每缝k==m,出列一个,out_cnt++
		}
		i++;//每个循环结尾都有i++,好用来计算p[i],跟链表方法里的p=p->next类似。
		if(i==n)
		{
			i=0;
		}
	}
	while(*p==0)//跳过出列元素,找到剩下的那个
	{
		p++;
	}
	printf("%d is left\n",*p);
	system("pause");
	return 0;
}


 


 

华为OD机试 - 报数问题 - 约瑟夫环(Java 2025 C卷 100分) 在这个问题中,n 个人站成一圈,每个人按照顺序报数,报到 3 的人退出圈子,直到只剩下一个人为止。要解决这个问题,我们可以使用数组或链表模拟这个过程,也可以使用数学方法直接找到最后剩下的人的位置。每次移除一个人,最多需要花费 O(n) 的时间,因为在最坏情况下需要遍历整个列表(比如在使用数组或链表时需要寻找并移除第 k 个元素)。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。报数序号为1的人最终报3,因此序号1的人退出圈子,最后剩下序号为2的那位。 阅读详情

相关推荐

实测有效防止colab自动断开连接

实测有效防止colab自动断开连接

Thebest_jack的博客 1万+

C++约瑟夫问题的10种解法【学不会私信我】

C++约瑟夫问题的10种解法【学不会私信我】

浪子回头 4612

频偏估计技术:从原理到5G应用的实战解析

本文深入解析了5G通信中的频偏问题及其核心技术。频偏如同调不准的旋钮,会导致信号失真与载波间干扰。文章详细拆解了整数倍与小数倍频偏估计两大核心方法,重点剖析了基于循环前缀和基于同步信号块的算法原理与优劣,并结合eMBB、mMTC、URLLC三大5G应用场景,提供了实战算法选择策略与参数调优避坑指南。

weixin_29218963的博客 262

4种方法解决约瑟夫环问题

本篇文章我们总结了关于约瑟夫环问题的几种解法,它们各有优势,读者可以根据实际需要自行选择。好的问题可以引发学习者的思考,寻找更优解可以让攀登者更上一层楼。希望本篇文章能对你有所帮助,我们共勉。

m0_73355263的博客 1万+

2022年全球市场微波等离子体CVD反应器总体规模、主要生产商、主要地区、产品和应用细分研究报告

据GIR (Global Info Research)调研,按收入计,2021年全球微波等离子体CVD反应器收入大约 百万美元,预计2028年达到 百万美元,2022至2028期间,年复合增长率CAGR为 %。

MARKETRESEARCH的博客 1137

置换矩阵、转置矩阵以及向量空间、子空间

置换矩阵、转置矩阵以及向量空间、子空间导读置换矩阵 导读 MIT矩阵分析课程之后的的二篇笔记。

qq_44677482的博客 1673

约瑟夫问题

约瑟夫问题是一个经典的数学问题,也是计算机科学中常见的数据结构和算法题目之一。我们可以使用数组、单链表、双向循环链表以及数学公式法等多种方法。

C语言实战大全 2296

TIA博途WINCC的触摸屏VB脚本入门指南(嵌入式)

通过编写事件处理程序,您可以响应触摸屏元素的各种事件,并实现自定义的功能。本文将为您提供TIA博途WINCC触摸屏VB脚本的入门指南,帮助您了解基本的脚本编写和嵌入式开发。假设我们有一个名为"Button1"的按钮元素,当用户点击该按钮时,触发相应的事件处理程序,并在触摸屏上显示一条消息。然后回到触摸屏界面编辑器,在按钮元素的属性窗口中找到"按下"事件,并选择刚才创建的脚本文件作为事件处理程序。现在,当用户点击按钮时,触摸屏将执行相应的事件处理程序,并显示一条消息框,内容为"按钮被点击了!

CodeSageX的博客 4418

约瑟夫问题的几种解决方法

约瑟夫问题的几种解决方法

weixin_58473601的博客 3423

华为OD机试双机位B卷 - 比赛的冠亚季军 (C++ & Python & JAVA & JS & GO)

华为OD机试双机位B卷 比赛的冠亚季军,提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解。 华为OD机试 比赛的冠亚季军

qq_45776114的博客 703

【Flutter 问题系列第 16 篇】如何防止软键盘弹出后顶掉内容

Flutter 如何防止软键盘弹出后顶掉内容

“Allen Su”的博客 3316

约瑟夫环问题详解

在牛客网上做到一道题,是约瑟夫环的变型,所以借此学习一下新知识,并且巩固一下对题目意思的理解,这一篇仅作约瑟夫环问题的解释,下一篇再写题目: 1.首先,我们先来了解一下什么是约瑟夫环问题: 讲一个比较有意思的故事:约瑟夫是犹太军队的一个将军,在反抗罗马的起义中,他所率领的军队被击溃,只剩下残余的部队40余人,他们都是宁死不屈的人,所以不愿投降做叛徒。一群人表决说要死,所以用一种策略来先后杀...

tingyun_say的博客 14万+

新手必看!手把手教你如何在飞牛NAS上玩转Docker容器!(飞牛Nas(fnOS)如何创建Docke容器以及Compose部署项目)

新手必看!手把手教你如何在飞牛NAS上玩转Docker容器!(飞牛Nas(fnOS)如何创建Docke容器以及Compose部署项目)

XiaoqiangClub的博客 1万+

【算法】约瑟夫环问题

链表算法篇

博客网站地址: https://arsenova.xyz 我会将优快云上的博客重修一部分迁移到网站上。 文章会做同步更新,但我不会在这个糟糕的平台多待1秒。下面是我要说的话,save your time. keep going 1390

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

pku1781约瑟夫环问题

<br />【题意】<br />典型的约瑟夫环杀人问题,N是给定的,M定为2,求最后胜利者,如N=5,则最后是3获胜。。。<br /> <br /> <br />开始写的超了时,也可以想到的,在自己编译器里都没有立刻出结果何况OJ里呢?代码如下:<br />#include<stdio.h><br />#include<string.h><br />int Joseph(int n){<br />    int i=2,a=0,b;<br />    while(i<=n){<br />        b=

坐井观天 1012

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

五、两种方法求解:约瑟夫环

题目描述:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。 解法一:基于数组实现 public void Solution(int totalNum, int countNum) { int size = totalNum, c...

贾腾升的博客 220

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

约瑟夫环 详解

简介 所有人围成一圈,顺时针报数,每次报到q的人将被杀掉,被杀掉的人将从房间内被移走 然后从被杀掉的下一个人重新报数,继续报q,再清除,直到剩余一人 做法一:模拟 可以用数组,flag标记死亡,一直往前数到q,直到杀了n-1个人为止 也可以用链表,直接移除杀死的人 做法二:q==2时的规律 对于q为2的情况,有个简单的方法。 假设2^n个人,从1开始数,那么最后活下来的那个...

QAQ 1883

约瑟夫环的问题1

n个人做成一圈,顺时针由1开始给他们编号,然后由第一个人进行报数,数到m的人出局,接着下一个人又从1开始报数,只剩最后一个人的时候求这个人的编号特例:当m = 2的时候① n = 2^k如果只有2个人,显然剩余的为1号如果有4个人,第一轮除掉2,4,剩下1,3,3死,留下1 。如果是8个人,先除去2,4,6,8,之后3,7,剩下1,5,除去5,又剩下1了递推,起始我们仔细分析也就是每次除去一半的元...

qq_31837563的博客 316

约瑟夫环问题(1)----Wikipedia上的原文解答

Josephus Problems:        There are people standing in a circle waiting to be executed. After the first person is executed, a certain number of people are skipped and one person is executed. Then,

wens07的专栏 638

猫抓老鼠c语言程序,猫抓老鼠问题C++实现一例(约瑟夫环问题)

今天偶然在网上看到了猫抓老鼠问题,当时也没多想,只觉得网上给出的程序的确有很多需要改进的地方,就闷头闷脑的用 循环链表 和 递归 写了一个算法实现,后来发现这个问题实际上是经典的约瑟夫环问题的变种,那个晕啊。而且有很多数学的方式来改进。。。。5555。。。看来算法部分要恶补,嗯嗯。。。问题:一、问题描述现有n个老鼠围成一圆圈,有一只猫从任意位置开始吃老鼠,每次都隔一个老鼠吃,请给出最后一个老鼠的编...

weixin_36337389的博客 1597

约瑟夫环,绕圈报数

这里用了笨办法,手动模拟,复杂度是o(n^2)

puppet_pic的博客 181

装逼!如何用一行代码解决约瑟夫环问题

点击蓝色“五分钟学算法”关注我哟 加个“星标”,天天中午 12:15,一起学算法 作者 | 帅地 来源 | 苦逼的码农 约瑟夫环问题算是很经典的题了,估计大家都听说过,然后我就在一次笔试中遇到了,下面我就用 3 种方法来详细讲解一下这道题,最后一种方法学了之后保证让你可以让你装逼。 问题描述:编号为 1-N 的 N 个士兵围坐在...

墨鱼菜鸡 474

微软面试100题系列---约瑟夫环问题

题目 n个数字形成1个圈,数字从0开始。每次从这个圈中删除第m个数字(当前数字为第1个数字),求出这个圈中剩下的最后一个数字;实现 方法1 单循环链表 思路:将n个节点形成一个不带头节点的单循环链表,设置一个计数器count(初始化为1)统计第几个数字;如果count=m,则删除当前节点,count=1,当前节点前移;否则继续向前遍历,count++; 代码实现: public class

bh_xiaoxinba的博客 320

In Danger(二分+打表+找规律(约瑟夫环))

题目来源:https://vjudge.net/problem/POJ-1781 【题意、思路】 因为这道题是在约瑟夫环题集出现的,但是刚写过一个裸模板题,发现这个数据最大是99000000,如果用vector模拟过程的话,肯定会超时,所以就打表找了下规律,然后打了1~99的表,输出的结果是(就是最终结果): 1 1 3 1 3 5 7 1 3 5 7 9 11 13

Crazy 533

大家看看我写的约瑟夫环(O(N))算法有没有问题

  约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人会被杀死;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到剩下一个人生存。     n = 9,k = 1,m = 5  【解答】   出局人的顺序为5,1,7,4,3,6,9,2,8。   题目引用了 百度百科  http...

4 the simplicity and beauty 143
上一篇: 带头结点和不带头结点的单链表的尾插法以及各种操作
下一篇: 分支限界法解决装载问题之FIFO队列方式的总结
eric802
博客等级 码龄17年 24粉丝 10原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值