今天老师布置了一个作业,要求我们用js来写一个猴子选大王的代码。其实就是约瑟夫环的问题。
题目为:n只猴子围坐成一个圈,按顺时针方向从1到n编号。然后从1号猴子开始沿顺时针方向从1开始报数,报到m的猴子出局,再从刚出局猴子的下一个位置重新开始报数,如此重复,直至剩下一个猴子,它就是大王。设计并编写程序,实现如下功能:
(1) 要求由用户输入开始时的猴子数n、报数的最后一个数m。
(2) 给出当选猴王的初始编号
思路:
在n<m的时候,即要报的数字大于现在已有的猴子的时候,很简单,只要每次m%现有猴子数字取余,得到的余数就是出局的猴子,但是当余数为0时就是最后一只猴子出局。然后弄一个判断,在只剩一个猴子的时候跳出循环,这只猴子便是大王。
但是在n>=m的时候,情况就比较复杂了,因为第一轮每个猴子都轮一遍的时候,只要是m的倍数都出局,然而在最后几只猴子数小于m的时候,就对下一轮的报数有影响了,比如4只猴子,报数3。那么第一轮第三只猴子出局,此时剩下1,2,4三只猴子,第四只猴子报1。这样对第二轮的情况就开始有变化了,如果此时n,m的数字比较大,那么后面的影响也会越来越大,情况就复杂了。
看了很多的例子都是用了队列,无意看到一个用数组的,结构简单多了,用一个step和outnum来计数。但是我发现在m==1是,程序不知道为什么会出错,就会吧所有的猴子都出局,所以我加了一个判断。
function a_game(pNum,out)
{
var monkey_num = [];
for(var i=1;i<=pNum;i++){
monkey_num.push(i);
}
var step=0;
if (out==1) {
return monkey_num[monkey_num.length-1];
} else{
while(monkey_num.length>1)
{
var outnum=0;
var len=monkey_num.length;
for (var i = 0; i<len; i++)
{
step++;
if(step==out)
{
step=0;
console.log("出局:"+monkey_num[i-outnum]);
monkey_num.splice(i-outnum,1);
outnum++;
}
}
}
return monkey_num[0];
}
};
console.log("大王是"+a_game(3,2));