程序员面试金典——番外篇之约瑟夫问题1

程序员面试金典——番外篇之约瑟夫问题1

Solution1:我的答案。脑子是个好东西,希望我总是带着他~
该算法模拟了游戏过程,不算好。
要理清逻辑关系,因果关系,再下笔~

class Joseph {
public:
    int getResult(int n, int m) {
        // write code here
        if(n <= 0 || m <= 0)
            return -1;
        vector<bool> temp(n, false);
        int index = 0, count_m = 0, nums_false = n;
        while(1) {
            if(temp[index] == true) 
                index = (index + 1) % n;
            else {
                count_m++;
                if(count_m == m) {
                    temp[index] = true;
                    nums_false--;
                    if(nums_false == 0)
                        return index + 1;//这,就是答案!
                    else {
                        count_m = 0;
                        index = (index + 1) % n;
                    }
                }
                else 
                    index = (index + 1) % n;
            }
        }
        return -1;
    }
};

Solution2:小技巧啊~
参考网址:https://www.nowcoder.com/profile/5263754/codeBookDetail?submissionId=13380131
思路:求出了递推公式,真牛逼
把n个人的编号改为0~n-1,然后对删除的过程进行分析。
第一个删除的数字是(m-1)%n,记为k,则剩余的编号为(0,1,…,k-1,k+1,…,n-1),下次开始删除时,顺序为(k+1,…,n-1,0,1,…k-1)。
f ( n , m ) 表示从(0~n-1)开始删除后的最终结果。
q ( n 1 , m ) 表示从(k+1,…,n-1,0,1,…k-1)开始删除后的最终结果。
f ( n , m ) = q ( n 1 , m )

下面把(k+1,…,n-1,0,1,…k-1)转换为(0~n-2)的形式,即
k+1对应0
k+2对于1

k-1对应n-2
转化函数设为 p ( x ) = ( x k 1 ) % n , p ( x ) 的逆函数为 p 1 ( x ) = ( x + k + 1 ) % n
f ( n , m ) = q ( n 1 , m ) = p 1 ( f ( n 1 , m ) ) = ( f ( n 1 , m ) + k + 1 ) % n ,又因为 k = ( m 1 ) % n
f ( n , m ) = ( f ( n 1 , m ) + m ) % n ;

最终的递推关系式为

f ( 1 , m ) = 0 ; ( n = 1 )

f ( n , m ) = ( f ( n 1 , m ) + m ) % n ; n > 1

代码如下

class Joseph {
public:
    int getResult(int n, int m) {
        // write code here   
        int pre = 0;
        for (int i = 2; i <= n; i++) {
            pre = (pre + m)%i;
        }
        return pre + 1;
    }
};

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324761935&siteId=291194637