约瑟夫环经典问题【数学公式法】

约瑟夫经典问题: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 = 1 n=1 n=1时,由于圈子中只有一个人,因此他就是获胜者,即 f ( 1 , k ) = 1 f(1,k)=1 f(1,k)=1
  • n > 1 n>1 n>1时,在第一轮将会离开一个人,剩下n-1个人,假设离开的是k’,满足 1 ≤ k ′ ≤ n 1≤k'≤n 1kn,且 k − k ′ k-k' kk是n的倍数
  • 由于 1 ≤ k ′ ≤ n 1≤k'≤n 1kn,因此 0 ≤ k ′ − 1 ≤ n − 1 0≤k'-1≤n-1 0k1n1,又由于 k − k ′ k-k' kk n n n的倍数,因此 ( k − 1 ) − ( k ′ − 1 ) (k-1)-(k'-1) (k1)(k1) n n n的倍数,因此 k ′ − 1 = ( k − 1 ) m o d k'-1=(k-1) mod k1=(k1)mod n n n k ’ = ( k − 1 ) m o d k’=(k-1) mod k=(k1)mod n + 1 n+1 n+1
  • x = f ( n − 1 , k ) x=f(n-1,k) x=f(n1,k),当第 k ′ k' k离开圈子后,获胜者的编号是从 k ′ + 1 k'+1 k+1开始的第 x x x个人的编号,因此 f ( n , k ) = ( k ′ m o d f(n,k)=(k' mod f(n,k)=(kmod n + x − 1 ) m o d n +x-1) mod n+x1)mod n + 1 = ( k + x − 1 ) m o d n +1=(k+x-1)mod n+1=(k+x1)mod n + 1 n + 1 n+1
  • x = f ( n − 1 , k ) x=f(n-1,k) x=f(n1,k)带入上述关系,可得: f ( n , k ) = ( k + f ( n − 1 , k ) − 1 ) m o d f(n,k)=(k+f(n-1,k)-1)mod f(n,k)=(k+f(n1,k)1)mod n + 1 n+1 n+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;
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值