首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >巨蟒系列中最大的产品

巨蟒系列中最大的产品
EN

Stack Overflow用户
提问于 2016-02-19 09:39:18
回答 5查看 3.7K关注 0票数 6

具有最大乘积的1000位数字中的四个相邻数字是:

9 × 9 × 8 × 9 = 5832

代码语言:javascript
复制
73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450

在拥有最大产品的1000位数字中找到13个相邻的数字.这种产品的价值是多少?

我对这个问题的解决办法是:

代码语言:javascript
复制
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  

有没有其他好的、有效率的方法来解决这个问题?因为我觉得我的不是很有效率

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2016-02-19 09:48:40

您可以在max函数中使用生成器表达式,并使用适当的key函数来计算子数字的乘积。为此,可以使用map函数将数字转换为整数,reduce (在python3.xfunctools.reduce中)计算整数的乘积。

代码语言:javascript
复制
>>> max((digits[i:i+13] for i in xrange(0, len(digits) - 12)), key=lambda x: reduce(mul, map(int, x)))
'5576689664895'

注意,如果在数字之间有新的行字符,则需要使用str.replace()方法删除它们。

代码语言:javascript
复制
digits = digits.replace('\n', '')

更优化的方法:

因为您每次都要处理13位数字,所以每次都可以使用容器来保存每次迭代中的数字,所以最好的选择是deque() form collections模块和maxlen=13,它的顺序是pop和push操作。然后,您可以计算前13位数的乘积,在每次推送和弹出时,您的初始产品应该被弹出项除以多个按推项。在每次迭代中,您只需使用最大乘积来保留序列。

代码语言:javascript
复制
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'])

演示:

代码语言:javascript
复制
container = deque(digits[:13], maxlen=13)
current_product = reduce(mul, map(int, container))
print cal_max_prod(container, current_product)
5576689664895
票数 5
EN

Stack Overflow用户

发布于 2016-02-19 10:05:26

为了简单起见,不要考虑13位数字,而要考虑3位数。前三位数字是:

代码语言:javascript
复制
731

他们的产品是21。接下来的三个数字是:

代码语言:javascript
复制
316

乘积是18,我们想要一个有效的算法,所以我们必须回答的一个问题是:我们能在恒定时间内从731的乘积中计算出316的乘积吗?

答案是肯定的:如果我们看数字,从731316,我们删除了7,增加了6。但是如果我们看乘积,我们已经除以7并乘以6,而不是计算7×3×1,然后3×1×6,然后1×6×7等等(每次执行n次乘法),我们可以从前一个乘积中计算下一个乘积(只执行1乘法和1除法)。

这是一个以线性时间运行的高效算法的草图:

代码语言:javascript
复制
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
票数 1
EN

Stack Overflow用户

发布于 2016-02-19 10:10:26

如果内存不是问题,则使用numpy。从他的数字基准测试来看,速度似乎比OP代码快10倍左右:

代码语言:javascript
复制
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]。示例:

代码语言:javascript
复制
no2('123456789101234123412351235324234324234')
1244160

基准测试

当对字符串进行基准测试时,我发现:

代码语言:javascript
复制
#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位数)进行基准测试时:

代码语言:javascript
复制
#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的性能会更好。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35501967

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档