该算法找到打开灯泡所需的开关

时间:2014-09-03 06:02:20

标签: algorithm math

假设您在N个开关的房间,并且在下一个房间里有一个灯泡。只有当某些指定的开关全部打开时,灯泡才会发光。

  • switches =所有开关的集合。 |switches| = N
  • required =需要打开以使灯泡发光的开关。

不需要的开关并不重要。

只有进入下一个房间,才能检查灯泡是否发光。您可以打开或关闭某些开关,转到下一个房间检查灯泡,然后重复此过程。让我们称之为ATTEMPT。

假设在最坏情况下有N个开关,找出required个开关集(使用优化策略)所需的最小尝试次数是多少?


例如,

  • switches = { 1, 2, 3 }
  • required = { 1, 2 }

让我们尝试一种天真的方法:

  • 打开{ 1, 2 },指示灯亮起。 (确保不需要开关3)
  • 开启{ 1, 3 },灯光不亮。 (确保需要开关2)
  • 开启{ 2, 3 },灯光不亮。 (确保需要开关1)

因此,通过3次尝试,我们可以确保required = { 1, 2 }

这个问题的优化算法是什么?

在最坏的情况下,考虑worst(N)切换,N是最小尝试。你能找到worst(N)

吗?

更新:如果您认为worst(N) = N,您能否提供正式证明?

3 个答案:

答案 0 :(得分:11)

证明最坏情况需要至少N次尝试

如果有N个开关,则可能有2 ^ N个可能的'必需'组,因为每个开关可以进入或离开'必需'组。

要区分2 ^ N个可能的集合,您可以考虑它,因为我们需要通过摆弄交换机来获得至少N位的信息。如果没有,那么有可能存在多于1套,它们都能适合我们目前所知的信息。

让我们假设有8种可能的配置(N = 3),我们可以选择配置子集并查询“required”配置是否在所选子集中。执行此操作的最佳方法类似于二进制搜索,实现log(2 ^ N)的复杂性,这只是N次尝试。如果我们使用少于3次尝试,我们将留下至少2种配置,我们无法确定哪种配置是正确的,因为每次尝试都将消除一半可能的配置。

回到最初的问题,让我们假设我们到目前为止使用K次尝试K< N.由于每次尝试都会提供1位信息(是的,它亮起/不亮,它没有点亮),每次尝试都可以消除一半可能的配置,我们将留下2 ^(NK)可能的配置K尝试。

要获得“必需”集合的仅1个不同的可能配置,我们将需要K = N,这将给出2 ^(N-N)= 2 ^ 0 = 1可能的配置。

这给了我们这个问题的下限,因为每次尝试都会提供1位信息(是的,它点亮/不亮,它不会点亮)。因此,我们至少需要N次尝试。

使用不超过N次尝试的可能解决方案

由于“非必需开关无关紧要”,如果我正确解释它,则意味着如果“必需”组外的开关打开,除了“必需”组中的开关外,灯光将会亮起还在上。由于我们有N次尝试使用(并且仍然使其最佳),我们可以使用以下解决方案: 对于每个开关(按顺序),打开除此开关之外的所有其他开关。 检查灯是否已关闭。如果关闭,唯一保持关闭的开关将处于“必需”设置中。

此解决方案将使用N次尝试(即使在更糟糕的情况下),它是最佳解决方案之一(如前所述)。

答案 1 :(得分:2)

  

假设在WORST CASE中有N个开关,找出所需开关集所需的最小尝试次数(使用优化策略)是什么?

蛮力的方式,检查所有可能的开关组合,直到灯亮,这将是O(2^N)(虽然我们可能会很幸运,并在我们第一次尝试后打开灯)。

通过更优化的搜索,可以在最差O(N)次尝试中找到所需的开关集。以下是始终O(N)的一种方式:

  • 翻开所有N开关:我们知道灯将亮起。

  • 关闭开关1。如果指示灯熄灭,则需要开关1,因此请将其重新打开。如果指示灯亮起,请关闭开关1,因为 这不是必需的。 (使用了一次尝试)。

  • 关闭开关2:如果指示灯熄灭,则需要开关2,然后重新打开。如果灯仍然亮着,请关闭开关2,因为它不是必需的。 (两次尝试使用)。

  • 对其余每个开关重复此检查。 (N尝试使用过。)

  • 尝试N后,我们将在开启位置留下所需开关的集合。

正如其他答案/评论中所述,也可以在最佳情况O(log(N))和最差情况O(N)找到所需的开关集:

  • 翻开所有N开关:我们知道灯将亮起。

  • 关闭第一个N/2开关。在灯保持亮起时,不需要这些开关,因此我们可以关闭开关。移至仍然打开的N/2个开关集,然后重复此步骤......

  • 如果灯熄灭,则至少需要其中一个N/2开关:重新打开开关,将组分成两半并重复上一步......

此算法是最差情况O(N),因为我们可能需要单独检查每个交换机(例如,如果有10个交换机且所需配置为0101010101)。

答案 2 :(得分:-1)

假设我们需要尝试N个开关的每个可能组合。我们可以将二进制数表示为0101,我们想检查每个二进制数。一种天真的方法是依次遍历每个数字:0000(全部关闭),0001(开关4打开),0010(开关3打开),0011(开关3和4打开)。注意如何从0001到0010实际上需要两个步骤来关闭4和3。

一个名为Gray code的更好的算法贯穿每个数字,这样每次只能切换一个数字。顺序是 0000,0001,0011,0010 0110,0111,0101,0100, 1100,1101,1111,1110, 1010,1011,1001,1000。

编辑:我认为这解决了一个稍微不同的问题,即某些开关上的灯需要关闭以使灯亮起。