题意:
- n个人成环,编号从1到n,从1开始报数,报数到m的人离开,由下一个人继续从1开始报数,循环n-1轮之后只剩下一个人,求这个人的初始编号是多少。
方法一:
思路分析:
- 因为最后只剩下一个人,所以我们可以从最后剩下的编号入手,看能不能倒推得到最开始的编号。首先画出图尝试找一下规律。
- 如上图所示,我们倒推:
 第四轮结束,最后留下来的人的编号为 1;
 第三轮结束,最后留下来的人的编号为 1+2=3; 3%2=1,编号为1;
 第二轮结束,最后留下来的人的编号为 1+2=3;
 第一轮结束,最后留下来的人的编号为 3+2=5(因为5>4) 所以5%4=1;
 第一轮开始,最后留下来的人的编号为 1+2=3;
- 我们可以得到规律是,(x+m-1)%n+1 是倒推的规律。此处先-1,+1的原因是初始从1开始编号,编号范围[1,n]与取模运算的值域范围[0,n-1]有差异,所以需要先减一后加一。如果编号范围是[0,n-1]的话,那么该规律应该为(x+m)%n
- 下面我们对于该规律(x+m)%n的一般化验证。
- 因此利用(x+m-1)%n+1的规律递推即可得到答案。
代码如下:
class Solution {
public:
    /**
     * 
     * @param n int整型 
     * @param m int整型 
     * @return int整型
     */
    int ysf(int n, int m) {
        // write code here
        int x=1;//x为留下来的人在最后一轮结束后的编号
        for(int i=2;i<=n;i++){
            x=(x+m-1)%i+1;//i为每轮人数数量。从2->n
        }
        return x;
    }
};复杂度分析:
时间复杂度:,循环n-1轮。
空间复杂度:。
方法二:
根据上述的递推式,也可使用递归的方式来解决。使用函数f(n,m)来表示人数为n时,最后留下来的人的编号。
有(f(n-1,m)+m-1)%n+1=f(n,m)。
代码如下:
class Solution {
public:
    /**
     * 
     * @param n int整型 
     * @param m int整型 
     * @return int整型
     */
    int helper(int n,int m){
        if(n==1)
            return 1;
        int x=helper(n-1,m);//下一轮的编号
        return (x+m-1)%n+1;//递推公式
    }
    int ysf(int n, int m) {
        // write code here
        return helper(n,m);
    }
};复杂度分析:
时间复杂度:,递归次数
。
空间复杂度:,递归深度
。



 京公网安备 11010502036488号
京公网安备 11010502036488号