将灯光切换到N的算法是什么?

时间:2014-05-14 03:48:11

标签: php algorithm

我今天在求职面试中遇到过这个问题,我完全被难过了。以下是对问题的描述:

你在房间内有一组1到100个灯,还有100个人。 i 第一个人走进房间并打开所有编号为 i 倍数的灯光。如果该灯已经打开,它们将关闭它(即它们将切换灯)。 100只是随机数 - 解决方案应该达到某个任意值 N (N ==灯数= =人数)。

例如,人1将打开所有灯(因为每个数字是1的倍数)。 Person 2将切换所有2的倍数(2,4,6,8等等)。这一直持续到第100个人。

当时,我觉得这可能与尝试确定N的素数有关,但我并不是100%肯定,所以我选择了一种蛮力的方法(这里大致相当)我在PHP中提供的内容:

function lights_toggled($number_of_lights) {
  $toggly = function($idx, $lights) {
    foreach($lights as $i => $light) {
      if($i % $idx == 0) {
        if($lights[$i]) {
          $lights[$i] = 0;
        } else if(!$lights[$i]) {
          $lights[$i] = 1;
        } 
      } 
    } 
    return $lights;
  };

  $lights = array_fill(1,$number_of_lights,0);
  for($i = 1; $i <= count($lights); $i++) {
    $lights = $toggly($i, $lights);
  }
  return array_sum($lights);
}

我认为一切都很好,直到我回到家并开始查看此功能的输入+输出。我做了这样的事情来得到一些样本结果:

$results = array();
for($j = 1; $j <= 100; $j++) {
  $number_of_lights_on = lights_toggled($j);
  $results[$number_of_lights_on][] = $j;
}
print_r($results);

很长,所以这里有一个输出的片段,用于当灯光开启时= = 3或4:

...
[3] => Array
    (
        [0] => 9
        [1] => 10
        [2] => 11
        [3] => 12
        [4] => 13
        [5] => 14
        [6] => 15
    )

[4] => Array
    (
        [0] => 16
        [1] => 17
        [2] => 18
        [3] => 19
        [4] => 20
        [5] => 21
        [6] => 22
        [7] => 23
        [8] => 24
    )
...

当灯光数量在9到15之间时,答案是3个灯亮。当灯的数量在16到24之间时,答案是4个灯亮。基本上,似乎当 x 灯作为答案返回时,总灯数的下限是 x ^ 2 ,它的上限是 x(x 2)

我开始在这里看到结构,但我不能指出这个结果是否遵循我不记得或不知道的算法。

1 个答案:

答案 0 :(得分:9)

这个问题通常被称为&#34;储物柜问题&#34; - 网络上有很多解释,例如:

http://mathforum.org/library/drmath/view/55812.html

它的要点是具有偶数个除数的那个将最终处于它们的起始状态,而具有奇数个除数的那些将最终处于相反的状态。虽然除数很大,但是,因素是

,这与素数有什么关系并没有多大关系。

特别是,具有奇数除数的数字都是.... drumroll ...完美的正方形。因为除了平方根之外的任何其他除数将具有匹配且不相等的除数,但是完美的正方形具有一个额外的除数(平方根),其不与另一个除数配对;它与自己配对。


请注意,对于你所说的特定问题(有多少是开放的),这意味着对于floor(sqrt(N))灯光的答案只是N,因为那是多少完美的正方形将小于或等于N