【问题标题】:Bulb Challenge in JavascriptJavascript 中的灯泡挑战
【发布时间】:2017-04-18 02:41:42
【问题描述】:

问题是“灯泡是通过电线连接的。每个灯泡都有一个与之关联的开关,但是由于接线错误,开关也会改变当前灯泡右侧所有灯泡的状态。给定一个初始所有灯泡的状态,找出打开所有灯泡所需按下的最少开关数。您可以多次按下同一个开关。

我在网上找到了这个答案,但我不能 100% 确定三元运算符在循环中做了什么。 var initialvar current 在做什么?

function bulbs(arr){
  var switched = 0;
    for(var i = 0; i < arr.length; i++){
      var initial = arr[i] === 1,
          current = (switched % 2 === 1)? !initial:initial;
      if(current === false){
        switched++;
      }
    }
  return switched;
}

【问题讨论】:

  • initial 等于 arr[i] 的值等于 1 的布尔返回值。current 为真或假(因为initial 是布尔值)。如果 switched 的当前值除以 2 得到的余数为 1,它将与 initial 相同,否则为逻辑非运算符,或者 ! 将布尔值更改为相反的值。
  • 但是为什么要使用模数并寻找余数呢?
  • switched %2 如何帮助实际更改数据?我正在寻找它在循环中的使用方式,而不是模数的通用定义
  • 这显然是一些课程/学校的问题。我认为使用这个网站是作弊。如果您自己进行研究,您将了解更多信息!

标签: javascript algorithm


【解决方案1】:

让我们从一个例子开始:在位置 0、1、2、3 给你 4 个灯泡;第二个灯泡打开:

[0, 1, 0, 0]

然后您从 0 到 3 遍历灯泡,每当遇到关闭的灯泡时,您将其打开并将所有开关反转到右侧。

[1, 0, 1, 1] // Bulb 0 is switched on, bulb 1, 2 and 3 inverted
 ^

[1, 1, 0, 0] // Bulb 1 is switched on, bulb 2 and 3 inverted
    ^

[1, 1, 1, 1] // Bulb 2 is switched on, bulb 3 inverted
       ^ 

[1, 1, 1, 1] // Bulb 3 is on, do nothing
          ^

您需要按三个开关才能打开所有灯泡。

现在让我们将上述模式编码为 JavaScript 函数:

function bulbs(arr) {
  var switched = 0;

  // Iterate through light bulbs from left to right:
  for (var i = 0; i < arr.length; i++) {
    var current = arr[i] === 1;               // True if bulb at position i is on
    if (current === false) {                  // It is off, so we press the switch
      switched++;
      for (var j = i; j < arr.length; j++) {  // Invert all bulbs to the right
        arr[j] = arr[j] === 1 ? 0 : 1;        // Invert 0 -> 1 and 1 -> 0
      }
    }
  }
  return switched;
}

这个算法是正确的,但是速度很慢。对于我们按下的每个开关,我们需要手动遍历右侧的所有灯泡并将它们一一反转。该算法的最坏情况运行时复杂度为 O(n²),其中 n 是灯泡的数量。

我们可以通过利用一个重要的观察来提高性能:位置i 处的灯泡的状态可以通过其初始状态(开或关)以及您在到达位置之前按下任何开关的次数来预测i:

  • 如果您事先按了偶数个开关(0、2、4、...次),则其状态等于其初始状态。
  • 如果您事先按下奇数个开关(1、3、5、...次),则其状态等于其初始状态的倒数。

现在,您已经将按下的开关数量存储在变量switched 中。为了确定switched 是否为奇数,您可以使用switched % 2 === 1。如果切换是奇数,我们必须通过执行!initial 来反转灯泡i 的初始状态以获取其当前状态:

current = (switched % 2 === 1) ? !initial : initial;

这种改进的算法不再具有内部 for 循环,因此在线性运行时复杂度 O(n) 的情况下速度更快。

【讨论】:

    【解决方案2】:

    我认为这个解决方案是不正确的,你可以试试这个特殊情况:

    灯泡([2,3,4,1,5]); // 返回:3

    它返回3。但正确的结果应该是2(包括:1,5)

    【讨论】:

    • 这不是问题的答案。不过,它当然适合作为评论。
    猜你喜欢
    • 2018-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-28
    • 2020-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多