程序员面试金典——番外篇之约瑟夫问题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)。
用
表示从(0~n-1)开始删除后的最终结果。
用
表示从(k+1,…,n-1,0,1,…k-1)开始删除后的最终结果。
则
。
下面把(k+1,…,n-1,0,1,…k-1)转换为(0~n-2)的形式,即
k+1对应0
k+2对于1
…
k-1对应n-2
转化函数设为
,
的逆函数为
。
则
,又因为
。
;
最终的递推关系式为
代码如下
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;
}
};