4

五个朋友排成一排喝着神奇的可乐。当第一个朋友喝了可乐,他就消失了,并变成了两份!之后,这些新副本排到最后,下一个朋友喝了魔法可乐,重复这个过程。

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

[Sheldon, Leonard, Penny, Rajesh, Howard]

在 Sheldon 喝完第一杯可乐后,这条线将如下所示:

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

伦纳德喝下可乐后,台词变成了这样:

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

等等...

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

因此,例如,doingconsole.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");

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

很明显,我的解决方案不仅不正确,而且似乎也无能为力。我该如何解决?

4

2 回答 2

5

一个基于零的递归提议,它返回数组的索引,这里是 length 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>');
}

于 2016-04-05T14:51:15.407 回答
0

好的,我们开始吧,这是一个非常简单的方法,我会想出一个更好的方法(我想了一半,我只需要把它放在一起)

function whoIsNext(names, index, multiplyFactor)
{
    var count = names.length;

    var fullLoops = 0;
    var currIndex = 0;

    while(currIndex <= index)
    {
        for(var i = 0; i < count; i++)
    {
            currIndex += Math.pow(multiplyFactor, fullLoops);
            if(currIndex > index)
            {
            return names[i];
            }
        }
        fullLoops++;
    }
}

这个想法是,每次人们做一个完整的循环时,同一个人来的数量增加一倍(countPerson = Math.pow(2, countFullLoops))。如果然后在设定的索引之前累积人数直到达到索引,那么您就会找到合适的人(我觉得我刚刚解释了一件非常容易的事情非常困难)。

您也可以根据需要替换任何输入(更改开始时的人数,更改乘数(有人说四倍可乐吗?))。

于 2016-04-05T16:36:55.080 回答