1

原题目

Sheldon, Leonard, Penny, Rajesh and Howard are in the queue for a "Double Cola" drink vending machine; there are no other people in the queue. The first one in the queue (Sheldon) buys a can, drinks it and doubles! The resulting two Sheldons go to the end of the queue. Then the next in the queue (Leonard) buys a can, drinks it and gets to the end of the queue as two Leonards, and so on.

For example, Penny drinks the third can of cola and the queue will look like this:

Rajesh, Howard, Sheldon, Sheldon, Leonard, Leonard, Penny, Penny

Write a program that will return the name of a man who will drink the n-th cola.

Note that in the very beginning the queue looks like that:

Sheldon, Leonard, Penny, Rajesh, Howard

题目: 有一个队列Sheldon, Leonard, Penny, Rajesh, Howard,排到的人,再次排到队尾,并将自己变成双倍。若给了一个队列names,排到的第r个人是谁?(题目比较绕,不知道该怎么描述?)

// 初始队列, 第一轮
["Sheldon", "Leonard", "Penny", "Rajesh", "Howard"]

// Sheldon排过队之后,重新到队尾,并将自己复制了一份
["Leonard", "Penny", "Rajesh", "Howard", "Sheldon", "Sheldon"]

// ...
// 第二轮,队列如下
["Sheldon", "Sheldon", "Leonard", "Leonard", "Penny", "Penny", "Rajesh", "Rajesh", "Howard", "Howard"]

// 第三轮,队列如下
["Sheldon", "Sheldon", "Sheldon", "Sheldon", "Leonard", "Leonard", "Leonard", "Leonard", "Penny", "Penny", "Penny", "Penny", "Rajesh", "Rajesh", "Rajesh", "Rajesh", "Howard", "Howard", "Howard", "Howard"]

My Solution

队列每轮过后,队列中的人数将变为原来的二倍。若初始队列的长度为len,第r人位于第m轮

第一轮:n=1,sum = len
第二轮:n=2,sum = len + len * 2
第三轮:n=4,sum = len + len * 2 + len * 4
...
第m轮:n=2^m, sum = len + len * 2 + …… + len * n

则,第r个人在第m轮的排名为:x = r + len * n - sum

则,第r个人的名字在初始队列中排名为t(数组下标为t-1),则:(t-1) * n < x <= t * n

所以,t = Math.ceil( x / n )

最后,代码整理如下:

function whoIsNext(names, r){
  var len = names.length;
  var sum = names.length;
  var n = 1;
  while(sum < r) {
    n *= 2;
    sum += len * n;
  }
  return names[Math.ceil((r + len * n - sum) / n) - 1]
}

Best Practices / Clever

function whoIsNext(names, r) {
  var l = names.length;
  while (r >= l) { r -= l; l *= 2; }
  return names[Math.ceil(names.length * r / l)-1];
}

对比

两个方法一个用加法,一个用减法,得出最后一轮的人数。个人也觉得 减法 更 clever 一点 ?


喻木同學
150 声望4 粉丝

有些光芒 即使微亮 绝不退让