本文主要是介绍[LeetCode][LCR187]破冰游戏——约瑟夫环,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
题目
LCR 187. 破冰游戏
社团共有 num 位成员参与破冰游戏,编号为 0 ~ num-1。成员们按照编号顺序围绕圆桌而坐。社长抽取一个数字 target,从 0 号成员起开始计数,排在第 target 位的成员离开圆桌,且成员离开后从下一个成员开始计数。请返回游戏结束时最后一位成员的编号。
- 示例 1:
输入:
num = 7, target = 4
输出:1
- 示例 2:
输入:
num = 12, target = 5
输出:0
- 提示:
1 <= num <= 10^5
1 <= target <= 10^6
思考
- 就本题这个数量级,直接模拟肯定会超时,必有某种数学方式进行求解
- 其实本题是著名的 ”约瑟夫环“ 问题,描述如下:
约瑟夫环(Josephus problem)最初的版本可以追溯到古代历史。这个问题据说最早出现在犹太历史学家弗拉维约斯·约瑟夫斯(Flavius Josephus)的著作《犹太古史》中。在这个传奇式的故事中,约瑟夫斯和他的40个士兵被罗马军队包围。他们决定宁可自杀也不被俘虏,于是他们决定围成一个圈,按照一定的规则自杀,以避免被捕。
问题的描述是:约瑟夫斯和他的士兵为了避免被俘,决定站在一个圆圈内,并且每次从一个人开始,依次数到第k个人,然后将被淘汰的人移出圆圈。那么最终存活下来的人是哪一个呢?
这个问题在数学和计算机科学领域中有很多变种和应用。常见的形式包括不同的起始位置和不同的淘汰间隔等。
解法
- 首先设一共有 num 个人,每轮去掉一个人,最终剩下一个人,也就是进行了 num-1 轮
- 游戏的关键不是每个人的编号,而是最终留下来的那个人在环中的位置
- 可以一次次进行游戏去掉一个个人,如果反过来,也可以恢复去掉的人,从一个人恢复到 num 个人
- 在只有一个人的情况下,解就是 0 号位置,也就是如果要把剩下的一个人也去掉,必然是去掉 0 号位置的人
- 那么怎么从一个人恢复到 num 个人呢?我们需要得到每次被去掉的数的位置:
1人->2人
num-1 轮去掉的数的位置 =(0号位置 + 每次跳跃数 target)% 加入新的数后本轮剩下的人数
num-1 轮去掉的数的位置=(0+target)%22人->3人
num-2 轮去掉的数的位置 =(num-1 轮去掉的数的位置 + 每次跳跃数 target)% 加入新的数后本轮剩下的人数
num-2 轮去掉的数的位置=(num-1 轮去掉的数的位置+target)%3
class Solution {
public:int iceBreakingGame(int num, int target) {// 每一次去除的人的位置 x// 在剩下一个人的情况下,// 这个位置是幸存者,// 也是下一轮剩0人的时候要去除的位置int x=0;for(int i=2; i<=num; ++i){x = (x+target)%i;}return x;}
};
这篇关于[LeetCode][LCR187]破冰游戏——约瑟夫环的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!