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
还有其他好的有效方法来解决这个问题吗?因为我认为我的效率不高
答案 0 :(得分:5)
您可以在max
函数中使用生成器表达式,并使用适当的key
函数来计算子数字的乘积。为此,您可以使用map
函数将数字转换为整数和reduce
(在python 3.X functools.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()
形式collections
模块{{1它的弹出和推送操作的顺序是O(1)。然后你可以计算出前13位数的乘积,并且在每次推送和弹出时你的初始产品应该被弹出的项目和多个按推项目除。并且在每次迭代中,您只需使用最大乘积保留序列。
maxlen=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'])
答案 1 :(得分:1)
如果你想提高效率,你会注意到在数字n到n + 12和n + 1到n + 13之间的乘积,你有12个共同因素。
所以让我们注意d i [0,999]中i的n位数,p i 以d i开头的m个连续数字的乘积(你的要求中m = 13):
在每次迭代中,当d i != 0时,你只做一个产品和一个师而不是12个产品,对于一个随机系列,这应该是10次中的9次
一如既往地优化算法,然后再考虑低级代码优化。但是......代码会更大或更复杂......
答案 2 :(得分:1)
为简单起见,请考虑3位数而不是13位数。前三位数字是:
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
答案 3 :(得分:0)
使用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
这也比OP代码提高了大约10倍。因此,除非数组不能适合RAM(但字符串可以),否则numpy表现更好。
答案 4 :(得分:0)
# I found this solution in this video (https://www.youtube.com/watch?v=oSZZn7krnX0&list=PLO1D3YWS7ep3Zrh8B4SrhIsyxneg23x29&index=10)
l='''
73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450'''
number = l.strip()
number = number.replace('\n','')
largest_mul = 0
lenght = 13
for i in range(len(number)):
mul = 1
for n in number[i:i+lenght]:
mul *= int(n)
if mul > largest_mul:
largest_mul = mul
print(largest_mul)
# 23514624000
答案 5 :(得分:-1)
data=list("
73167176531330624919225119674426574742355349194934\
96983520312774506326239578318016984801869478851843\
85861560789112949495459501737958331952853208805511\
12540698747158523863050715693290963295227443043557\
66896648950445244523161731856403098711121722383113\
62229893423380308135336276614282806444486645238749\
30358907296290491560440772390713810515859307960866\
70172427121883998797908792274921901699720888093776\
65727333001053367881220235421809751254540594752243\
52584907711670556013604839586446706324415722155397\
53697817977846174064955149290862569321978468622482\
83972241375657056057490261407972968652414535100474\
82166370484403199890008895243450658541227588666881\
16427171479924442928230863465674813919123162824586\
17866458359124566529476545682848912883142607690042\
24219022671055626321111109370544217506941658960408\
07198403850962455444362981230987879927244284909188\
84580156166097919133875499200524063689912560717606\
05886116467109405077541002256983155200055935729725\
71636269561882670428252483600823257530420752963450")
print(len(data))
lst=list()
while True:
x=list(data[0:13])
pro=1
for i in x:
pro*=int(i)
lst.append(pro)
data.pop(0)
if len(data)==12:
break
print(max(lst))
print(len(data))
print(lst[0])