【问题标题】:Optimizing sum of numbers in a list range优化列表范围内的数字总和
【发布时间】:2015-09-29 18:35:26
【问题描述】:

我正在尝试回答有关在线法官的问题,但我一直遇到时间限制问题。该问题的主要思想是解决列表的总和减去该列表中子列表的总和。完整问题规范可见 here.

这是我的代码:

import sys
lists = sys.stdin.read().strip().split('\n')

showScores = map(int, lists[1].split())
maximum = sum(showScores)
loops = map(int, lists[0].split())[1]

for i in range(2, loops+2):
    subList = lists[i].split()
    print maximum - sum(showScores[int(subList[0])-1 : int(subList[1])])

有没有更好的算法来解决这个问题?考虑到我必须执行多达 500,000 次循环,我应该如何处理?

【问题讨论】:

    标签: python algorithm list for-loop


    【解决方案1】:

    您可以避免为每个查询调用sum。无论切片的效率如何,您仍然需要在当前设置下迭代该范围以计算其总和。所以你需要优化你的算法,而不是代码。

    如果你有:

    S[i] = sum of the first i numbers
         = a[0] + a[1] + ... + a[i]
    

    你可以在O(n)中计算:

    S[i] = S[i - 1] + a[i]
    

    如何使用S 回答O(1) 中的每个查询?

    提示:如果您必须计算某个区间 [x, y] 的总和,我们将使用:

    S[y] = a[0] + a[1] + ... + a[x] + ... + a[y]
    S[x] = a[0] + a[1] + ... + a[x - 1] + a[x]
    

    【讨论】:

    • 尽管我同意提供提示而不是立即提供完整的解决方案,但我认为这种答案不适合 SO 的问答形式。它更适合评论。
    • @MaciejGol 评论太长了。如果您能找到更好的提示,但不会全部泄露,我会删除它。 OP要求一种方法,这就是这种方法。这是完整解决方案的一步。
    • 我不确定我是否理解您的暗示。我是否必须添加到子列表的开头并在子列表的末尾添加?
    【解决方案2】:

    @IVlad 在他的回答中给出了非常有用的提示,我将通过示例更进一步。只要您可以在循环之前预先计算值,循环执行的速度就会越快。在一个切片上运行sum() 每次都会为同一个切片返回相同的值,因此在循环之前预先计算总和。

    如果您生成第一个a 分数的总和列表,它将如下所示:

    first = [0, 5, 11, 18, 26, 29, 33, 38, 44, 45, 47]
    

    如果您还生成了最后一个 b 分数总和的列表,它将如下所示:

    last = [47, 42, 36, 29, 21, 18, 14, 9, 3, 2, 0]
    

    在你的循环中,你可以

    print first[a-1] + last[b]
    

    这比取一个切片的总和要快。

    【讨论】:

    • 总体思路是创建另一个总和列表并使用它来计算答案。这些例子真的很有帮助。
    猜你喜欢
    • 2013-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-12
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 2016-02-03
    相关资源
    最近更新 更多