请告诉我为什么这段代码运行良好时我的代码超时?

时间:2019-03-03 11:37:16

标签: python arrays algorithm

问题是 *从1索引的零数组和一个操作列表开始,对于每个操作,在两个给定索引(包括两个索引)之间为每个数组元素添加一个值。完成所有操作后,返回数组中的最大值。 *

这是我的代码

def arrayManipulation(n, queries):
    li = [0] * n
    for query in queries:
        a, b, c = map(int, [query[0], query[1], query[2]])
        for i in range(a-1, b):
            li[i] += c
    return max(li)

这是行之有效的代码

def arrayManipulation(n, queries):
    N, M = n, len(queries)
    li = [0] * n
    for i in range(M):
        a, b, k = map(int, [queries[i][0], queries[i][1], queries[i][2]])
        li[a-1] += k
        try:
            li[b] -= k
        except:
            pass

    t = li[0]
    for i in range(1, N):
        li[i] += li[i-1]
        if(li[i] > t):
            t = li[i]
    return t

我的代码在某些测试用例中给出了超时错误

1 个答案:

答案 0 :(得分:0)

第一个实现可能需要太多时间来运行nqueries的某些选择的原因,而第二个实现对于相同的输入可能会更快,原因是这两个函数具有不同的computational complexity

请考虑n的一千万(n = 10**7)值,以及一个queries列表,其中包含大小可比(或等于)n的范围,例如为queries = [(1, 10**7, 42)]*10

首次实施

对于该输入,第一个实现将执行li[i] += c行(10* 10 ** 7 = 10**8)次,这可能会引起注意(运行可能需要几秒钟)。想象一下,对于更高的n值和queries长度,该乘积将变得更大。

作为nlen(queries)的函数,按数量级的操作数将为:n*len(queries)

第二实施

相反,第二个函数经过优化,因此没有嵌套循环。

第一个循环内的操作:

for i in range(M):
    a, b, k = map(int, [queries[i][0], queries[i][1], queries[i][2]])
    li[a-1] += k
    try:
        li[b] -= k
    except:
        pass

预计运行M次(即len(queries))。

第二个循环中的操作:

for i in range(1, N):
    li[i] += li[i-1]
    if(li[i] > t):
        t = li[i]

将运行N次(等于n)。

因此,根据幅度nlen(query)的函数,第二个函数中的操作数将为:len(query) + n

例如,对于10个查询且n为10 ** 7,循环迭代将为10 + 10**7 ~= 10**7。因此,那里没有乘法,并且该函数的运行速度比第一个实现要快。

测量

您可以自己查看。首先,将第一个功能保存在名为solve1.py的文件中,将第二个功能保存在solve2.py中。然后在终端中运行以下命令:

运行第一个:

time python3 -c 'from solve1 import arrayManipulation;print(arrayManipulation(10000000, [(1, 10000000, 42)]*10))'

运行第二个:

time python3 -c 'from solve2 import arrayManipulation;print(arrayManipulation(10000000, [(1, 10000000, 42)]*10))'

在我的机器上,第一个大约需要8秒,而第二个大约需要1.8秒,这确认了第二个功能随着输入的增加而更快。