[LeetCode][LCR187]破冰游戏——约瑟夫环

发布于:2024-03-29 ⋅ 阅读:(21) ⋅ 点赞:(0)

题目

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

思考

  1. 就本题这个数量级,直接模拟肯定会超时,必有某种数学方式进行求解
  2. 其实本题是著名的 ”约瑟夫环“ 问题,描述如下:
  • 约瑟夫环(Josephus problem)最初的版本可以追溯到古代历史。这个问题据说最早出现在犹太历史学家弗拉维约斯·约瑟夫斯(Flavius Josephus)的著作《犹太古史》中。在这个传奇式的故事中,约瑟夫斯和他的40个士兵被罗马军队包围。他们决定宁可自杀也不被俘虏,于是他们决定围成一个圈,按照一定的规则自杀,以避免被捕。

  • 问题的描述是:约瑟夫斯和他的士兵为了避免被俘,决定站在一个圆圈内,并且每次从一个人开始,依次数到第k个人,然后将被淘汰的人移出圆圈。那么最终存活下来的人是哪一个呢?

  • 这个问题在数学和计算机科学领域中有很多变种和应用。常见的形式包括不同的起始位置和不同的淘汰间隔等。

解法

  1. 首先设一共有 num 个人,每轮去掉一个人,最终剩下一个人,也就是进行了 num-1 轮
  2. 游戏的关键不是每个人的编号,而是最终留下来的那个人在环中的位置
  3. 可以一次次进行游戏去掉一个个人,如果反过来,也可以恢复去掉的人,从一个人恢复到 num 个人
  4. 在只有一个人的情况下,解就是 0 号位置,也就是如果要把剩下的一个人也去掉,必然是去掉 0 号位置的人
  5. 那么怎么从一个人恢复到 num 个人呢?我们需要得到每次被去掉的数的位置:
1人->2人
num-1 轮去掉的数的位置 =(0号位置 + 每次跳跃数 target)% 加入新的数后本轮剩下的人数
num-1 轮去掉的数的位置=(0+target)%2

2人->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;
    }
};
本文含有隐藏内容,请 开通VIP 后查看