约瑟夫经典问题: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;
}

约瑟夫环经典问题【数学公式法】相关推荐

  1. 约瑟夫环问题的几种解法

    int mind01() {vector<int> vec;int n, m;scanf("%d%d",&n,&m);//初始化for (int i=1 ...

  2. 约瑟夫环递推公式的由来(约瑟夫环公式法)

    约瑟夫问题 约瑟夫问题是个著名的问题:N个人围成一圈,第一个人从1开始报数,报M的将被杀掉,下一个人接着从1开始报.如此反复,最后剩下一个,求最后的胜利者. 例如只有三个人,把他们叫做A.B.C,他们 ...

  3. 约瑟夫环——公式法(递推公式)

    约瑟夫问题 约瑟夫问题是个著名的问题:N个人围成一圈,第一个人从1开始报数,报M的将被杀掉,下一个人接着从1开始报.如此反复,最后剩下一个,求最后的胜利者. 例如只有三个人,把他们叫做A.B.C,他们 ...

  4. 【算法经典】 约瑟夫环问题

    [前言]本文讨论经典算法问题约瑟夫环问题的递归解法. 一.问题描述 作为算法中的经典问题,约瑟夫环问题自诞生以来有各种各样的变种描述,丢手绢.游戏获胜者.圆圈中最后剩下的数字.点名游戏等等,但都是同样 ...

  5. 2018沈阳k(经典的约瑟夫环)

    地址 K Let the Flames Begin 首先,对于经典的约瑟夫环问题,我们记f(n,m)f(n,m)f(n,m)表示初始有nnn个人,第mmm个出队的人是谁(从0号开始报数).则有递推式f ...

  6. 【图解经典算法题】如何用一行代码解决约瑟夫环问题

    约瑟夫环问题算是很经典的题了,估计大家都听说过,然后我就在一次笔试中遇到了,下面我就用 3 种方法来详细讲解一下这道题,最后一种方法学了之后保证让你可以让你装逼. 问题描述:编号为 1-N 的 N 个 ...

  7. (猴子选王)约瑟夫环方法4种方法之一——循环链表法

    话都在代码里 题目 //约瑟夫环的循环链表解法 #include <stdlib.h> #include <malloc.h> #include <stdio.h> ...

  8. C语言解决经典问题约瑟夫环--数组

    什么时约瑟夫环问题? 约瑟夫问题,是一个计算机科学和数学中的问题,在计算机编程的算法中,类似问题又称为约瑟夫环,又称"丢手绢问题". 问题的大致内容就是:一共有N个人,从1开始报数 ...

  9. 约瑟夫环问题(数学递推法)

    约瑟夫环问题起源于一个犹太故事: 罗马人攻占了桥塔帕特,41个人藏在一个山洞中躲过了这场浩劫.这41个人中,包括历史学家Josephus(约瑟夫)和他的一个朋友.剩余的39个人为了表示不向罗马人屈服, ...

最新文章

  1. 抢占式优先权调度算法
  2. 第27讲:令人抓狂的 JavaScript 混淆技术
  3. 【SQL】服务器环境下的SQL
  4. 【转】阿里技术专家详解DDD系列 第二讲 - 应用架构
  5. 万恶之源 - Python基础数据类型一
  6. 贪心法——区间覆盖问题
  7. 如何在 Web 开发中找到第一份工作?
  8. java plsql_在PLSQL中编译复杂的java(转)
  9. 多路测温系统C51语言,51单片机多路DS18B20温度测量程序
  10. MacOS壁纸文件夹如何查找
  11. 计算机基础知识高职版,计算机应用基础 课件教学全套课件(高职版大学计算机基础 第7章 计算机网络基础知识 课件.pptx...
  12. Typora配置阿里云图床详细教程(PicGo+阿里云OSS)
  13. 百度3D地球,高清地图!地形混合!
  14. iOS同时适配iPad横屏和iPhone竖屏
  15. JavaScript创建对象的方式
  16. 2021微信红包封面免费领取最新攻略 春节免费微信红包封面序列号大全
  17. 贪吃蛇游戏 c++代码 ↑,↓,→,←分别控制蛇的方向 增加蛇长 随机生成食物 吃食物 吃撞墙 撞到自己
  18. Debug与Release版本的区别
  19. 网站安全狗安装时服务器名,解决网站安全狗安装后访问网站需要用户名密码的方法...
  20. 视频格式基础知识:让你了解MKV、MP4、H.265、码率、色深等等.

热门文章

  1. 全志v3s学习笔记(5)——主线Linux编译与烧录
  2. 如果你有100万,你会选择先买车,还是先买房?
  3. address sanitizer memcpy param overlap
  4. 最近有公司的大数据哥们反馈OKI是0
  5. Python写代码遇到的问题集锦
  6. 什么是EOS(不一样的角度看柚子)
  7. 联想安装Linux系统
  8. android 流式布局官方,Android 流式布局
  9. qq for android v4.6 用户右边的手机图标,QQ2014没了?安卓版手机QQ v4.6全面体验
  10. 如何用excel制作图表?