2017-06-06 57 views
-1

一个经典的数学谜题,取自代码 的问题陈述“有n个球首先关闭,首先打开所有的球。关闭每一个第二个灯泡,在第三轮中,每隔一个灯泡切换一次(如果灯泡熄灭则开启,如果灯泡开启则关闭);对于第i轮,您切换每一个灯泡;对于第n轮,您只需切换最后一个灯泡,找出n轮后有多少个灯泡。“Python范围函数步长大小列表分配超出范围的错误,模拟了一个谜题

我意识到问题本身有一个简明的解决方案,但我想模拟灯泡开关的问题。但随着步长增加,我遇到列表索引超出范围错误,我该如何处理这个错误?我希望只有在索引仍然有效时才能切换这些值。

def bulbSwitch(self, n): 
     """ 
     :type n: int 
     :rtype: int 
     """ 
     bulbs= [0]*n 
     step=0 
     for i in range(n): 
      step += 1 
      for s in range(0, n, step): 
       bulbs[s+i]=0 if bulbs[s]==1 else 1 #this line produces error 
     print bulbs 
+1

为什么'灯泡[S + I]'? – jonrsharpe

+0

@jonrsharpe我不想每次都从灯泡[0]开始,当步长为2时,我想从灯泡[1]开始,步长为3,从灯泡[2]开始等。 – codeAligned

+0

I明白,但为什么要添加当前回合的数量? – jonrsharpe

回答

3

正如其他人指出的那样,问题是s+i索引。环路中s的最大值为n-1,所以如果向其中添加任何内容,则将运行到列表的末尾。

你说你要开始与bulbs[1]step是2,bulbs[2]step为3等,所以刚开始的范围,而不是有:

for step in range(1, n+1): # this avoids separate `i` vs. `step` variables 
    for s in range(step-1, n, step): # start in the right place 
     bulbs[s] = 0 if bulbs[s] == 1 else 1 

编辑

也许这是更轻松? (这里我用了一个+1代替-1的。)

for step in range(n): # this avoids separate `i` vs. `step` variables 
    for s in range(step, n, step+1): # start in the right place 
     bulbs[s] = 0 if bulbs[s] == 1 else 1 

EDIT 2

只是确保它的工作......我添加了一个测试(其中通过):

import math 

def bulb_switch(n): 
    bulbs = [0] * n 

    for step in range(n): # this avoids separate `i` vs. `step` variables 
     for s in range(step, n, step+1): # start in the right place 
      bulbs[s] = 0 if bulbs[s] == 1 else 1 

    return sum(bulbs) 

for i in range(1000): 
    assert math.floor(math.sqrt(i)) == bulb_switch(i) 
+0

它运作良好,我学会了如何更正确地使用range()。代码返回正确的开/关灯泡数组,但当n很大时(9999),由代码OJ认为太慢。 – codeAligned

+0

FWIW,我试着用'bulbs [s]^= 1'来优化它,但它看起来有点慢(但我只是用bash时间命令测试它,而不是正确的'timeit'测试)。我想'if'测试并将列表项设置为一个常量比算术更快。好吧。 :) –

+0

@ user53008我假设leetcode有意传递大值,以确保通过测试,您必须编写数学解决方案(随着'n'的增加,速度不会变慢)。 – smarx