约瑟夫环经典问题【数学公式法】
约瑟夫经典问题:N个人围成一圈,第一个人从1开始报数,报M的将被杀掉,下一个人接着从1开始报。如此反复,最后剩下一个,求最后的胜利者。题目可见:找出游戏的胜利者
首先考虑常规解法:队列模拟。用一个队列模拟环,报到M的数字移除队列,其余的数字添加到队列末尾,直到队列中的数字个数只有一个为止,时间复杂度是O(nm),每m次离开一个,一共进行n次,空间复杂度是O(n)。代码如下:
int findTheWinner(int n, int k) {k%=n; //取余if(k==0) k=n;;queue<int>q;for(int i=1;i<=n;i++) q.push(i);while(q.size()!=1){int t=k-1;while(t){q.push(q.front());q.pop();t--;}q.pop(); //每轮离开一个}return q.front();
}
可以看到,即使采用了取余操作,时间复杂度最坏的情况也是O(n^2)的,因此我们可以采用其他的方法。
- 假设用f(n,k)f(n,k)f(n,k)表示n个人围成一个圈,每轮报数为k的人离开圈子时的获胜者编号
- 当n=1n=1n=1时,由于圈子中只有一个人,因此他就是获胜者,即f(1,k)=1f(1,k)=1f(1,k)=1
- 当n>1n>1n>1时,在第一轮将会离开一个人,剩下n-1个人,假设离开的是k’,满足1≤k′≤n1≤k'≤n1≤k′≤n,且k−k′k-k'k−k′是n的倍数
- 由于1≤k′≤n1≤k'≤n1≤k′≤n,因此0≤k′−1≤n−10≤k'-1≤n-10≤k′−1≤n−1,又由于k−k′k-k'k−k′是nnn的倍数,因此(k−1)−(k′−1)(k-1)-(k'-1)(k−1)−(k′−1)是nnn的倍数,因此k′−1=(k−1)modk'-1=(k-1) modk′−1=(k−1)mod nnn,k’=(k−1)modk’=(k-1) modk’=(k−1)mod n+1n+1n+1
- 令x=f(n−1,k)x=f(n-1,k)x=f(n−1,k),当第k′k'k′离开圈子后,获胜者的编号是从k′+1k'+1k′+1开始的第xxx个人的编号,因此f(n,k)=(k′modf(n,k)=(k' modf(n,k)=(k′mod n+x−1)modn +x-1) modn+x−1)mod n+1=(k+x−1)modn +1=(k+x-1)modn+1=(k+x−1)mod n+1n + 1n+1
- 将x=f(n−1,k)x=f(n-1,k)x=f(n−1,k)带入上述关系,可得:f(n,k)=(k+f(n−1,k)−1)modf(n,k)=(k+f(n-1,k)-1)modf(n,k)=(k+f(n−1,k)−1)mod n+1n+1n+1
递归:
int findTheWinner(int n, int k) {if (n == 1) {return 1;}return (k + findTheWinner(n - 1, k) - 1) % n + 1;
}
迭代:
int findTheWinner(int n, int k) {int winner = 1;for (int i = 2; i <= n; i++) {winner = (k + winner - 1) % i + 1;}return winner;
}
约瑟夫环经典问题【数学公式法】相关推荐
- 约瑟夫环问题的几种解法
int mind01() {vector<int> vec;int n, m;scanf("%d%d",&n,&m);//初始化for (int i=1 ...
- 约瑟夫环递推公式的由来(约瑟夫环公式法)
约瑟夫问题 约瑟夫问题是个著名的问题:N个人围成一圈,第一个人从1开始报数,报M的将被杀掉,下一个人接着从1开始报.如此反复,最后剩下一个,求最后的胜利者. 例如只有三个人,把他们叫做A.B.C,他们 ...
- 约瑟夫环——公式法(递推公式)
约瑟夫问题 约瑟夫问题是个著名的问题:N个人围成一圈,第一个人从1开始报数,报M的将被杀掉,下一个人接着从1开始报.如此反复,最后剩下一个,求最后的胜利者. 例如只有三个人,把他们叫做A.B.C,他们 ...
- 【算法经典】 约瑟夫环问题
[前言]本文讨论经典算法问题约瑟夫环问题的递归解法. 一.问题描述 作为算法中的经典问题,约瑟夫环问题自诞生以来有各种各样的变种描述,丢手绢.游戏获胜者.圆圈中最后剩下的数字.点名游戏等等,但都是同样 ...
- 2018沈阳k(经典的约瑟夫环)
地址 K Let the Flames Begin 首先,对于经典的约瑟夫环问题,我们记f(n,m)f(n,m)f(n,m)表示初始有nnn个人,第mmm个出队的人是谁(从0号开始报数).则有递推式f ...
- 【图解经典算法题】如何用一行代码解决约瑟夫环问题
约瑟夫环问题算是很经典的题了,估计大家都听说过,然后我就在一次笔试中遇到了,下面我就用 3 种方法来详细讲解一下这道题,最后一种方法学了之后保证让你可以让你装逼. 问题描述:编号为 1-N 的 N 个 ...
- (猴子选王)约瑟夫环方法4种方法之一——循环链表法
话都在代码里 题目 //约瑟夫环的循环链表解法 #include <stdlib.h> #include <malloc.h> #include <stdio.h> ...
- C语言解决经典问题约瑟夫环--数组
什么时约瑟夫环问题? 约瑟夫问题,是一个计算机科学和数学中的问题,在计算机编程的算法中,类似问题又称为约瑟夫环,又称"丢手绢问题". 问题的大致内容就是:一共有N个人,从1开始报数 ...
- 约瑟夫环问题(数学递推法)
约瑟夫环问题起源于一个犹太故事: 罗马人攻占了桥塔帕特,41个人藏在一个山洞中躲过了这场浩劫.这41个人中,包括历史学家Josephus(约瑟夫)和他的一个朋友.剩余的39个人为了表示不向罗马人屈服, ...
最新文章
- 抢占式优先权调度算法
- 第27讲:令人抓狂的 JavaScript 混淆技术
- 【SQL】服务器环境下的SQL
- 【转】阿里技术专家详解DDD系列 第二讲 - 应用架构
- 万恶之源 - Python基础数据类型一
- 贪心法——区间覆盖问题
- 如何在 Web 开发中找到第一份工作?
- java plsql_在PLSQL中编译复杂的java(转)
- 多路测温系统C51语言,51单片机多路DS18B20温度测量程序
- MacOS壁纸文件夹如何查找
- 计算机基础知识高职版,计算机应用基础 课件教学全套课件(高职版大学计算机基础 第7章 计算机网络基础知识 课件.pptx...
- Typora配置阿里云图床详细教程(PicGo+阿里云OSS)
- 百度3D地球,高清地图!地形混合!
- iOS同时适配iPad横屏和iPhone竖屏
- JavaScript创建对象的方式
- 2021微信红包封面免费领取最新攻略 春节免费微信红包封面序列号大全
- 贪吃蛇游戏 c++代码 ↑,↓,→,←分别控制蛇的方向 增加蛇长 随机生成食物 吃食物 吃撞墙 撞到自己
- Debug与Release版本的区别
- 网站安全狗安装时服务器名,解决网站安全狗安装后访问网站需要用户名密码的方法...
- 视频格式基础知识:让你了解MKV、MP4、H.265、码率、色深等等.