五个朋友正在排队喝魔术可乐。当第一个朋友喝可乐时,他消失了,成两份!之后,这些新副本将转到行尾,下一位朋友将喝可乐,并重复此过程。
例如,假设我们有以下朋友:
[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>');
}