《剑指OFFER》中约瑟夫环详细解法

首先让我们来了解一下约瑟夫问题的背景故事:

这个问题是以弗拉维奥·约瑟夫命名的,他是1世纪的一名犹太历史学家。他在自己的日记中写道,他和他的40个战友被罗马军队包围在洞中。他们讨论是自杀还是被俘,最终决定自杀,并以抽签的方式决定谁杀掉谁。约瑟夫斯和另外一个人是最后两个留下的人。约瑟夫斯说服了那个人,他们将向罗马军队投降,不再自杀。约瑟夫斯把他的存活归因于运气或天意,他不知道是哪一个。 —— 【约瑟夫问题】维基百科

然后让我们回到题目:

0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。

例如,A、B、C、D、E这5个字母组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个字母依次是C、A、E、B,因此最后剩下的字母是D。 ——来自《剑指OFFER》

这里我用excel画了一个淘汰示意图,最后只剩下D活了下来。
我们可以发现,如果确定了N和M也就确定了最后活下来的那个字母的标号,我称之为天选之人

这里我们需要注意的是,每次删除以后,都是直接从后面一位数字开始计数,所以我把被删除字母提到前面了,到最后,我们可以发现,**天选之人的编号为0!**而且,无论如何N和M怎么变化,天选之人最后的编号始终会为0!,这样,咱们就可以反推得出。

淘汰示意图下面我们把被删除的字母补回到后面去,然后把溢出的字母搬回到前面去得到下列的操作在这里插入图片描述所以,我们可以推出公式:F(5,3)=(F(4,3)+3)%5
所以就有了下面的公式:
F(N,M)=(F(N-1,M)+M)%N

但是N=1 的时候又是另外一种情况,所以,这个完整的递推公式为:
在这里插入图片描述下面给出C语言的参考代码:`

int Joseph(int N,int M)
{
	int alive = 0;
	int i = 0;
	for(i=2;i<N+1;i++)
	{
		alive = (alive + M) % i
	}
	return alive;
}

参与评论 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

奇奇怪怪没有脑袋

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值