Python中的原始计算器

时间:2018-04-17 04:40:32

标签: python dynamic-programming

我编写了以下代码,它执行了应该执行的操作并传递了测试以及时间和内存限制。但是,它需要90%的时间限制。无论如何要加快速度吗?

其次,我已经看到其他解决方案似乎更直接,并且没有为最多n的整数构建所有最小操作的列表。在DP中,我们应该这样做吗?换句话说,我们是不是应该始终自下而上建立一个表?

最后,如何让代码更具可读性?

# Use Python 3

""" You're given a calculator with only 3 operations: (-1, //2, //3).
find the minimum number of operations and the sequence of numbers to
go from 1 to n"""
import sys

input = sys.stdin.read()
n = int(input)


def operations(n):
    """
    :param n: integer
    :return: The list of the minimum number of operations to reduce n to 1
    for each integer up to n. """
    lst = [0] * n
    for index in range(1, n):
        nodes = [1 + lst[index - 1]]
        for k in (2, 3):
            if (index + 1) % k == 0:
                nodes.append(1 + lst[((index + 1) // k) - 1])
        lst[index] = sorted(nodes)[0]

    return lst


master_sequence = list(enumerate(operations(n), 1))

end = master_sequence[-1]
minimum_operations = end[1]
sequence = []

while end != (1, 0):
    step = [item[0] for item in master_sequence if
            (end[1] - item[1]) == 1 and (end[0] - item[0] == 1 or end[0] % 
item[0] == 0)][0]
    sequence.append(step)
    end = master_sequence[step - 1]

print(minimum_operations)
for s in sequence[::-1]:
    print(s, end=' ')
print(n)

1 个答案:

答案 0 :(得分:0)

DP只是意味着使用子问题结果来缩短时间/空间复杂性,因此它经常建立,但并不一定意味着每个值。注意:您也可以使用heap搜索来解决此问题,这不会触及每个节点,我认为在时间和可能的空间方面相当接近。

使用DP获得相同结果的更短方法:

In []:
n = 10

# Define the operations and their condition for application:
ops = [(lambda x: True, lambda x: x-1),
       (lambda x: x%2==0, lambda x: x//2),
       (lambda x: x%3==0, lambda x: x//3)]

# Construct the operations count for all values up to `n`
min_ops = [0]*(n+1)
for i in range(2, n+1):
    min_ops[i] = min(min_ops[op(i)] for cond, op in ops if cond(i))+1

# Reconstruct the path
r = []
while n:
    r.append(n)
    n = min((op(n) for cond, op in ops if cond(n)), key=min_ops.__getitem__)

len(r)-1, r[::-1]

Out[]
(3, [1, 3, 9, 10])

针对不同n的一些快速时间安排:

10: 22 µs ± 577 ns per loop
1000: 1.48 ms ± 12.3 µs per loop
10000: 15.3 ms ± 325 µs per loop
100000: 159 ms ± 2.81 ms per loop

当我运行你的代码时,我得到了:

10: 15.7 µs ± 229 ns per loop
1000: 4.55 ms ± 318 µs per loop
10000: 27.1 ms ± 896 µs per loop
100000: 315 ms ± 7.13 ms per loop