Javascript 循环数字
因此,这就是给出的问题 你在一个有100把椅子的房间里。椅子从1到100依次编号 在某个时间点,1号主席将被要求离开。2号主席的人将被跳过,3号主席的人将被要求离开。这种跳过一个人并要求下一个人离开的模式将继续循环,直到剩下一个人,即幸存者 这就是我的答案。我相信这是正确的答案,我在纸上也做了大约10次,每次都得到74次。 这是个骗人的问题还是什么?因为我不知道接下来该怎么办 这是JSFIDLEJavascript 循环数字,javascript,josephus,Javascript,Josephus,因此,这就是给出的问题 你在一个有100把椅子的房间里。椅子从1到100依次编号 在某个时间点,1号主席将被要求离开。2号主席的人将被跳过,3号主席的人将被要求离开。这种跳过一个人并要求下一个人离开的模式将继续循环,直到剩下一个人,即幸存者 这就是我的答案。我相信这是正确的答案,我在纸上也做了大约10次,每次都得到74次。 这是个骗人的问题还是什么?因为我不知道接下来该怎么办 这是JSFIDLE var控制台={ 日志:函数{ document.body.innerHTML+=s+“”; } }
var控制台={
日志:函数{
document.body.innerHTML+=s+“
”;
}
};
var=arr[];
对于(变量i=1;i 1){
console.log('removing'+chairArr[j]);
椅架拼接(j,1);
j++;
如果(j>=椅子长度){
console.log('--Finished pass');
log('---数组状态:');
控制台日志(chairArr);
j=(j==椅子长度)?0:1;
}
}
console.log('---最终结果:'+chairArr);
//结果74
您在这里描述的是约瑟夫问题,可以使用动态规划来解决:
function josephus(n, k)
{
if (n == 1) {
return 1;
} else {
return ((josephus(n-1, k) + k - 1) % n) + 1;
}
}
alert(josephus(100, 2));
资料来源:
n
表示椅子的数量,k
表示第k个人离开
这里的结果是73
更新
不幸的是,我没有正确地阅读这个问题。上面的代码解决了一个稍微不同的问题;第一轮没有杀死第一个人,而是杀死了第二个人。成为幸存者取决于细节:)
解决代码问题相当简单,从第一轮中的第一人开始,而不是第三人
var chairArr = [];
for (var i = 1; i <= 100; i++){
chairArr.push(i);
}
var j = 0;
while (chairArr.length > 1) {
chairArr.splice(j, 1);
j = (j + 1) % n;
}
var chairArr=[];
对于(变量i=1;i 1){
椅架拼接(j,1);
j=(j+1)%n;
}
索引稍有变化,就有约瑟夫问题了。在传统的公式中,1人杀死2人,3人杀死4人,以此类推。要转换为这种形式,根据问题的状态,杀死1人,然后通过减去1重新编号2-100人,得到1-99人
格雷厄姆、克努特和帕塔什尼克在《具体数学》第二版第1.3节中对约瑟夫斯问题进行了很好的处理,包括对其起源于公元70-73年犹太人起义的描述。Wikipedia和Wolfram MathWorld都有关于这个问题的文章,Wikipedia甚至包括Josephus在犹太战争中的原始描述
这本书给出了解决方案的一个稍微复杂的递归,以及一个更简单的算法。如果人数是n
,并且n=2^l+m
其中l
尽可能多,那么答案是2m+1
。因此,由于99=2^6+35
,解决方案是2*35+1=71
。但是您需要反转重新编号,因此真正的答案是72
然而,就你的编程问题而言,你为什么不把第一个人移到圈的最后,把第二个人移到圈的最后,作为你的基本操作呢。因此,对于5
人,[1,2,3,4,5]
,您将删除第一个获取[2,3,4,5]
,并将新的第一个元素移动到获取[3,4,5,2]
的末尾
var killAndRotate = function(array) { // say [1,2,3,4,5]
var dead = array.shift(), // dead = 1, array = [2,3,4,5]
skipped = array.shift(); // skipped = 2, array = [3,4,5]
array.push(skipped); // array = [3,4,5,2]
}
然后主循环变成:
while (chairArray.length > 1) {
killAndRotate(chairArray);
}
alert(chairArray[0]); // or console.log, or return.
// In turn, array is:
// [1,2,3,4,5]
// [3,4,5,2]
// [5,2,4]
// [4,2]
// [2] and we alert, log, or return 2.
补充
找到原始约瑟夫问题的结果的简单方法是:
如果有2^l
人,那么在第一次通过时,所有偶数的人都被杀死,所以第一个人仍然活着
1 2 3 4 5 6 7 8
X X X X
现在有2^(l-1)
人。同样,第一个人幸存下来:
1 2 3 4 5 6 7 8
X X X X
X X
重复这个过程;第一个人每次通过都能幸存下来,最后一个也能幸存下来
现在,假设有m
额外的人有m<2^l
。这里,l=3
和m=5
。杀死第一批死亡的人
1 2 3 4 5 6 7 8 9 10 11 12 13
X X X X X Y
现在,有2^l
人离开了,person2m+1=11
是第一个排队的人。所以他活了下来
还应该指出,添加新的索引变量和拼接可能会导致程序员错误。因为您只需要从前面移除,然后添加到后面,所以请使用数组的基本方法。在我看来,答案是72。当您意识到可以跳过数字而不是删除数字时,代码就会变得非常简短和直接
var chairArr = [];
for (var i = 1; i <= 100; i++)
chairArr.push(i);
for (i = 1; i < chairArr.length-2; i = i + 2)
chairArr.push(chairArr[i]);
console.log('--- Final result: ' + chairArr[i]);
var chairArr=[];
对于(var i=1;i您不需要迭代来找到结果,有一个公式可用于获得最终主席:
function findChair (input) {
return (input - Math.pow(2, Math.floor(Math.log2(input)))) * 2 || (input === 1 ? 0 : input)
}
对于原始的Josephus问题,你可以去掉偶数,公式可以简化:
function findChair (input) {
return (input - Math.pow(2, Math.floor(Math.log2(input)))) * 2 + 1
}
原始问题最酷的地方在于,您可以使用二进制。例如:
100=1100100
取第一个“1”并将其放在最后:
1001001=73老师说答案应该是什么?当问题说“1应该先去”时,为什么你先把这个人从椅子上移开?为什么j
从2开始?这是我收到的回答。看起来很可靠,但不幸的是你刚刚偏离了目标。再拿一个l看看你是否看到了错误。你说“坐在椅子上的人将被要求离开”。第一次你没有删除#1,所以你需要将变量j调整为零。正如你所说的问题是,坐在椅子上的人#1将首先离开,但你从#3开始。你为什么认为这是一个骗人的问题?我不明白为什么它是73而不是72。我读了维基文章,但不明白。当我在纸上这样做的时候去掉1,3,5等等,我得到72。请给我解释一下为什么这是答案。你是说递归吗?约瑟夫问题去掉了偶数,而不是奇数。@user2677350我现在必须运行,
function findChair (input) {
return (input - Math.pow(2, Math.floor(Math.log2(input)))) * 2 + 1
}