Javascript 循环数字

Javascript 循环数字,javascript,josephus,Javascript,Josephus,因此,这就是给出的问题 你在一个有100把椅子的房间里。椅子从1到100依次编号 在某个时间点,1号主席将被要求离开。2号主席的人将被跳过,3号主席的人将被要求离开。这种跳过一个人并要求下一个人离开的模式将继续循环,直到剩下一个人,即幸存者 这就是我的答案。我相信这是正确的答案,我在纸上也做了大约10次,每次都得到74次。 这是个骗人的问题还是什么?因为我不知道接下来该怎么办 这是JSFIDLE var控制台={ 日志:函数{ document.body.innerHTML+=s+“”; } }

因此,这就是给出的问题

你在一个有100把椅子的房间里。椅子从1到100依次编号

在某个时间点,1号主席将被要求离开。2号主席的人将被跳过,3号主席的人将被要求离开。这种跳过一个人并要求下一个人离开的模式将继续循环,直到剩下一个人,即幸存者

这就是我的答案。我相信这是正确的答案,我在纸上也做了大约10次,每次都得到74次。 这是个骗人的问题还是什么?因为我不知道接下来该怎么办

这是JSFIDLE

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
人离开了,person
2m+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
}