五个朋友正在排队喝魔术可乐。当第一个朋友喝可乐时,他消失了,成两份!之后,这些新副本将转到行尾,下一位朋友将喝可乐,并重复此过程。

例如,假设我们有以下朋友:

[Sheldon, Leonard, Penny, Rajesh, Howard]


在谢尔顿喝完第一杯可乐之后,这条线将如下所示:

[Leonard, Penny, Rajesh, Howard, Sheldon, Sheldon]


伦纳德喝了可乐之后,这条线变成了这样:

[Penny, Rajesh, Howard, Sheldon, Sheldon, Leonard, Leonard]


等等...

我的目标是用JavaScript编写一个函数,该函数给定一个包含行中人物姓名和数字N的数组,它将返回第N个喝魔术可乐的人的名字。

因此,例如,执行console.log(whoIsNext([Sheldon, Leonard, Penny, Rajesh, Howard], 1))应该返回Sheldon

为此,我编写了以下代码:

function whoIsNext(names, r){
  var fistInLine;

  if(r <= names.length){
    return names[r-1];
  }else{

    while(r > names.length){
      fistInLine = names.shift();
      names.push(fistInLine, fistInLine);
    }
    return names[r-1];
  }
}


此功能在以下情况下效果很好:

names = ["Sheldon", "Leonard", "Penny", "Rajesh", "Howard"];
Test.assertEquals(whoIsNext(names, 1), "Sheldon");


但是测试失败:

names = ["Sheldon", "Leonard", "Penny", "Rajesh", "Howard"];
Test.assertEquals(whoIsNext(names, 52), "Penny");


如果我尝试使用很大的数字,例如:

names = ["Sheldon", "Leonard", "Penny", "Rajesh", "Howard"];
Test.assertEquals(whoIsNext(names, 7230702951), "Leonard");


它甚至不会停止运行(永远需要)。

所以很明显,我的解决方案不仅不正确,而且似乎也不有效。我该如何解决?

最佳答案

从零开始的递归建议,它返回数组的索引,此处的长度为base = 5


                           1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3
number 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
index  0 1 2 3 4 0 0 1 1 2 2 3 3 4 4 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 0 0 0 0 0

  
  它变得可见,该模式基于5,每轮上升2倍。

5 -> 10- > 20 -> 40

  
  计算示例

                Array after step
                0 1 2 3 4 5 6 7 8 9
  0: 0 Sheldon  |
  1: 1 Leonard  | |
  2: 2 Penny    | | |
  3: 3 Rajesh   | | | |
  4: 4 Howard   | | | | |
  5: 0 Sheldon    | | | | |
  6: 0 Sheldon    | | | | | |
  7: 1 Leonard      | | | | | |
  8: 1 Leonard      | | | | | | |
  9: 2 Penny          | | | | | |
 10: 2 Penny          | | | | | |
 11: 3 Rajesh           | | | | |
 12: 3 Rajesh           | | | | |
 13: 4 Howard             | | | |
 14: 4 Howard             | | | |
 15: 0 Sheldon              | | |
 16: 0 Sheldon              | | |
 17: 0 Sheldon                | |
 18: 0 Sheldon                | |
 19: 1 Leonard                  |
 20: 1 Leonard                  |
 21: 1 Leonard
 22: 1 Leonard





var friends = ['Sheldon', 'Leonard', 'Penny', 'Rajesh', 'Howard'],
    base = friends.length;

function getIndex(n, i) {
    i = i || base;
    if (n < i) {
        return Math.floor(n * base / i);
    }
    return getIndex(n - i, 2 * i);
}

var i = 0, index;

document.write(friends[getIndex(1 - 1)] + '<br>');          // "Sheldon"
document.write(friends[getIndex(52 - 1)] + '<br>');         // "Penny"
document.write(friends[getIndex(7230702951 - 1)] + '<hr>'); // "Leonard"

for (i = 0; i < 200; i++) {
    index = getIndex(i);
    document.write(i + ': ' + index + ' ' + friends[index] + '<br>');
}

07-26 05:34