具有最大乘积的1000位数字中的四个相邻数字是:
9 × 9 × 8 × 9 = 5832
73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450在拥有最大产品的1000位数字中找到13个相邻的数字.这种产品的价值是多少?
我对这个问题的解决办法是:
def no(x):
previous=0
i=0
t=1
while i !=987:
for num in x[i:i+13]:
no=int(num)
t=no*t
if t>previous:
previous = t
i=i+1
t=1
return previous 有没有其他好的、有效率的方法来解决这个问题?因为我觉得我的不是很有效率
发布于 2016-02-19 09:48:40
您可以在max函数中使用生成器表达式,并使用适当的key函数来计算子数字的乘积。为此,可以使用map函数将数字转换为整数,reduce (在python3.xfunctools.reduce中)计算整数的乘积。
>>> max((digits[i:i+13] for i in xrange(0, len(digits) - 12)), key=lambda x: reduce(mul, map(int, x)))
'5576689664895'注意,如果在数字之间有新的行字符,则需要使用str.replace()方法删除它们。
digits = digits.replace('\n', '')更优化的方法:
因为您每次都要处理13位数字,所以每次都可以使用容器来保存每次迭代中的数字,所以最好的选择是deque() form collections模块和maxlen=13,它的顺序是pop和push操作。然后,您可以计算前13位数的乘积,在每次推送和弹出时,您的初始产品应该被弹出项除以多个按推项。在每次迭代中,您只需使用最大乘积来保留序列。
from operator import mul
from collections import deque
from copy import copy
def cal_max_prod(container, current_product):
max_container = {'seq': copy(container), 'prod': current_product}
for i in digits[13:]:
popped_item = int(container.popleft())
container.append(i)
try:
push_item = int(i)
current_product = (current_product / popped_item) * push_item
except ZeroDivisionError:
if '0' not in container:
current_product = reduce(mul, map(int, container))
else:
if current_product > max_container['prod']:
max_container['prod'] = current_product
max_container['seq'] = copy(container)
return ''.join(max_container['seq'])演示:
container = deque(digits[:13], maxlen=13)
current_product = reduce(mul, map(int, container))
print cal_max_prod(container, current_product)
5576689664895发布于 2016-02-19 10:05:26
为了简单起见,不要考虑13位数字,而要考虑3位数。前三位数字是:
731他们的产品是21。接下来的三个数字是:
316乘积是18,我们想要一个有效的算法,所以我们必须回答的一个问题是:我们能在恒定时间内从731的乘积中计算出316的乘积吗?
答案是肯定的:如果我们看数字,从731到316,我们删除了7,增加了6。但是如果我们看乘积,我们已经除以7并乘以6,而不是计算7×3×1,然后3×1×6,然后1×6×7等等(每次执行n次乘法),我们可以从前一个乘积中计算下一个乘积(只执行1乘法和1除法)。
这是一个以线性时间运行的高效算法的草图:
def maxproduct(number, digits):
"""Calculate the maximum product of the n-adjacent digits of number."""
zeros = 0
product = 1
result = 0
# Calculate the first, initial product.
for x in number[:digits]:
x = int(x)
if x:
product *= int(x)
else:
# This digit is 0. This will make our product zero
# too (losing information about other digits) and will
# also cause trouble with division later. Instead of
# storing the zero in the product, we increment a counter.
zeros += 1
if not zeros:
# This product is the highest we have seen so far.
result = product
# Calculate the other products with the remaining digits.
for i in range(digits, len(number)):
# Digit to remove.
x = int(number[i - digits])
# Digit to add.
y = int(number[i])
if x:
product //= x
else:
# The digit to remove is 0.
zeros -= 1
if y:
product *= y
else:
zeros += 1
if not zeros and product > result:
result = product
return result发布于 2016-02-19 10:10:26
如果内存不是问题,则使用numpy。从他的数字基准测试来看,速度似乎比OP代码快10倍左右:
import numpy as np
def no2(x,d=13):
k = len(x)-d
t = np.ones(k,dtype=int)
xa = np.fromiter(map(int,tuple(x)),dtype=int)
for i in range(d): #xrange on python2.x
t *= xa[i:k+i]
return np.max(t)若要获取返回最大值的数字,请将np.max(t)替换为x[np.argmax(t):np.argmax(t)+d]。示例:
no2('123456789101234123412351235324234324234')
1244160基准测试
当对字符串进行基准测试时,我发现:
#OP approach:
%timeit -n 100 no(x)
100 loops, best of 3: 3.49 ms per loop
#Kasramvd approach:
%timeit -n 100 no3=max((s[i:i+13] for i in range(0, len(s) - 12)), key=lambda x: reduce(mul, map(int, x)))
100 loops, best of 3: 4.22 ms per loop
#Andrea approach:
%timeit -n 100 no4(x,13)
100 loops, best of 3: 777 µs per loop
#numpy approach:
%timeit -n 100 no2(x)
100 loops, best of 3: 315 µs per loop当内存和速度都是问题时:
当使用字符串10^4倍长(即10^7位数)进行基准测试时:
#numpy
%timeit -n 10 no2(x5)
10 loops, best of 3: 2.2 s per loop
#OP code
%timeit -n 1 no(x5)
1 loop, best of 3: 37 s per loop
#Andrea code
%timeit -n 1 no4(x5,13)
1 loop, best of 3: 8.01 s per loop这也是一个大约10倍的改进比OP代码。因此,除非数组不能放入RAM(但字符串可以),否则numpy的性能会更好。
https://stackoverflow.com/questions/35501967
复制相似问题