计算平方因子列表的python代码优化
我参加了codewars网站上的python挑战赛。我遇到了以下挑战: 42的除数是:1,2,3,6,7,14,21,42。这些除数的平方是:1,4,9,36,491964411764。除数的平方和是2500,也就是50*50,一个平方计算平方因子列表的python代码优化,python,arrays,algorithm,Python,Arrays,Algorithm,我参加了codewars网站上的python挑战赛。我遇到了以下挑战: 42的除数是:1,2,3,6,7,14,21,42。这些除数的平方是:1,4,9,36,491964411764。除数的平方和是2500,也就是50*50,一个平方 给定两个整数m,n(1对您的代码有几种优化,但最大的优化是当ans*ans大于x时停止: def square_root(x): ans = 0 while True: ans += 1 sqans = ans*a
给定两个整数m,n(1对您的代码有几种优化,但最大的优化是当
ans*ans
大于x
时停止:
def square_root(x):
ans = 0
while True:
ans += 1
sqans = ans*ans
if sqans == x:
return ans
elif sqans > x:
return 0
while
中的条件可以删除,因为现在测试是在平方值上进行的
通过这种优化,使用250500
案例,我从8秒下降到了0.07秒
但这仍然不令人满意。一般来说,包含中断或返回条件的算法至少是O(n)
,即使可以节省时间,复杂性也太高
只需检查四舍五入的平方根的平方,就可以做得更好:
def square_root(x):
ans = int(x**0.5 + 0.5) # rounded just in case it goes below the actual value (float inaccuracy)
sqans = ans*ans
return 0 if sqans !=x else x
我将执行时间再除以2(由确认)
除此之外(这并没有加快多少速度,但值得一提):
无需将map
转换为sum
中的list
:
sq_sum = sum(map(lambda x: x**2,fact(i)))
另外,fact
可以避免循环到max number。循环到max number除以2并将max number添加到列表中是等效的。max number/2上方不存在更多的除数
def fact(m):
return [i for i in range(1,m//2+1) if m%i == 0] + [m]
最终编辑:这仍然很慢,因为在fact
中使用了列表理解。我可以使用生成器来大幅缩短时间,并在其外部添加m*m
:
def sqfact(m):
return (i*i for i in range(1,m//2+1) if m%i == 0)
最后的代码,现在运行得很快,我有0秒的时间
def sqfact(m):
return (i*i for i in range(1,m//2+1) if m%i == 0)
def square_root(x):
ans = int(x**0.5 + 0.5)
return 0 if ans*ans !=x else x
def list_squared(m, n):
# your code
fac=[]
for i in range(m,n+1):
sq_sum = sum(sqfact(i)) + i*i # add i square outside
if square_root(sq_sum):
fac.append([i,sq_sum])
return fac
我已经更新了效率非常低的事实函数。现在,我没有迭代到
m
的完整值来找到它的因子,我只去了sqrt(m)
。这大大减少了运行时间。这背后的逻辑很简单,所以我没有详细说明。下面是为我工作的新代码
def fact(m):
#determining the lower factors i.e., smaller than sqrt(m)
fac = [i for i in range(1, int(m**0.5) + 1) if m%i == 0]
#determining the higher factors i.e., larger than sqrt(m)
fac = fac + [m//i for i in range(1, int(m**0.5) + 1) if m%i == 0]
return sorted(list(set(fac))) #in order to get rid of duplicate factors
两个细节:在
返回ans
之后,您不需要中断
,因为这将结束函数。ans=ans+1
也可以缩短为ans+=1
。另外sum(list(map(lambda x:x**2,fact(i))
=>sum(map(lambda x:x**2,fact(i)))无需转换为list以比ans=ans+1慢的速度传递到sumis ans+=1?我将后者更改为@numbermiac建议的前者。现在我的示例测试运行时已经慢了很多。我认为不会再慢了。您是否也根据Jean的建议更改了sum
?如果您更改了,我不知道这是否是r伊森。谢谢你的评论。我可以通过修改平方根函数大约500倍来减少运行时间,尽管方式不同。还有关于事实()的评论函数很有用,但不会显著减少运行时间。即使有了这些改进,代码的效率似乎仍不足以让web提交接受它。请检查我的编辑。检查square更简单。感谢您的评论和努力。我已经投票并接受了此答案,但我仍然无法提交给代码战中的网页提交。它仍然需要一些优化。确实,还有一些其他的大优化。检查我的最终编辑。感谢接受,现在应该可以了。再次感谢。但是这仍然是非常低效的。我现在已经给出了一个答案,它现在非常有效,能够通过挑战。请通过我的回答。我会感谢你的回答。我已经测试过了(没有列表理解)速度差被square\u root
函数相形见绌,我放弃了它。我想我应该用更大的数字进行测试,因为差异很明显。你仍然需要我对square\u root
函数进行优化。a,d顺便说一句,我认为不存在重复因子,除非m是平方,所以将1减为1循环结束边界的e,没有集合
的东西你就可以走了。
def fact(m):
return [i for i in range(1,m//2+1) if m%i == 0] + [m]
def sqfact(m):
return (i*i for i in range(1,m//2+1) if m%i == 0)
def sqfact(m):
return (i*i for i in range(1,m//2+1) if m%i == 0)
def square_root(x):
ans = int(x**0.5 + 0.5)
return 0 if ans*ans !=x else x
def list_squared(m, n):
# your code
fac=[]
for i in range(m,n+1):
sq_sum = sum(sqfact(i)) + i*i # add i square outside
if square_root(sq_sum):
fac.append([i,sq_sum])
return fac
def fact(m):
#determining the lower factors i.e., smaller than sqrt(m)
fac = [i for i in range(1, int(m**0.5) + 1) if m%i == 0]
#determining the higher factors i.e., larger than sqrt(m)
fac = fac + [m//i for i in range(1, int(m**0.5) + 1) if m%i == 0]
return sorted(list(set(fac))) #in order to get rid of duplicate factors