【发布时间】:2019-03-22 22:55:44
【问题描述】:
问题定义:
这是codewars的问题。
定义一个自反向功率序列,S,为:
S(0) = 0
S(1) = 1
S(2) = 1^2 + 2 = 3
S(3) = 1^3 + 2^2 + 3 = 8
...
S(n) = 1^n + 2^(n-1) + ... + (n-1)^2 + n
实现一个接受 2 个参数(num_dig 和 ord_max)的函数,并找到序列中小于 num dig 的最小数字,而 num dig 也具有 ord_max 个数字。
如果有一个数字的位数正确,结果应该是一个数组,格式如下:
[True, smallest found term]
[False, -1]
这些是一些例子:
n-th Term Term Value
1 0
2 1
3 3
4 8
5 22
6 65
7 209
8 732
9 2780
10 11377
11 49863
12 232768
13 1151914
14 6018785
所以样本测试包括:
min_length_num(5, 10) == [True, 10] # 10th term has 5 digits
min_length_num(7, 11) == [False, -1] # no terms before 13th has 7 digits
min_length_num(7, 14) == [True, 13] # 13th term already has 7 digits
我的方法:
我创建了一个生成器,它产生幂级数 S 的所有值,直到值 n:
def seq(n):
for i in range(n):
s = range(i+1)
j = i+1
tot = 0
while j > 0:
for k in s:
tot += k**j
j -=1
break
yield tot
然后我检查生成器的值,然后:要么在遇到具有所需位数的第一个值时立即返回 True,否则返回 False:
def min_length_num(num_dig, ord_max):
i = 1
for n in seq(ord_max):
if len(str(n)) == num_dig:
return [True, i]
elif len(str(n)) > num_dig:
break
i +=1
return [False, -1]
这会通过所有测试,但不会完成测试过程,因为它会超时。输入范围假设 ord_max
我对生成器不是很精通,所以也许我在那里做错了什么,或者做得不恰当。我会很感激一些帮助。谢谢。
编辑:另一种解决方案。
由于我知道 ord_max
p = [n for n in seq(1000)]
def min_length_num(num_dig, ord_max):
i = 1
for k in p[:ord_max]:
if len(str(k)) == num_dig:
return [True, i]
elif len(str(k)) > num_dig:
break
i +=1
return [False, -1]
这更快并且解决了我的问题,但我发现它是一个非常丑陋的解决方案,更像是一个肮脏的黑客。我想要更好的东西。
【问题讨论】:
-
使用
pow而不是**。前者使用平方取幂,这比简单乘法快一个数量级。 -
谢谢@Rishav 我不知道。但是,我认为这并不能解决问题。
-
@Rishav:你确定它们不同吗?在 CPython 中,至少它们都使用相同的底层代码来计算 x 的 y 次方(特别是
long_pow)
标签: python algorithm python-2.7 performance generator