【问题标题】:Optimizing the run time of the nested for loop优化嵌套 for 循环的运行时间
【发布时间】:2017-09-29 15:27:17
【问题描述】:

我刚刚开始使用竞争性编程,在编写了某些问题的解决方案后,我得到了 RUNTIME exceeded 的错误。

max( | a [ i ] - a [ j ] | + | i - j | )

a 是元素列表,i,j 是获取 ma​​x() 所需的索引strong> 以上表达式。

这是一个简短但完整的代码sn-p。

t = int(input()) # Number of test cases
for i in range(t):
    n = int(input()) #size of list
    a = list(map(int, str(input()).split())) # getting space separated input
    res = []
    for s in range(n): # These two loops are increasing the run-time
        for d in range(n):
            res.append(abs(a[s] - a[d]) + abs(s - d))
    print(max(res))

Input File此链接可能会过期(希望有效)

  • 1
  • 1
  • 0

C 语言排行榜的运行时间为 5 秒Python 为 35 秒,而此代码需要 80 秒。 p>

它是一个在线法官,因此独立于机器。numpy 不可用

保持简单我是python新手。

感谢阅读。

【问题讨论】:

  • 为什么不直接对数组进行排序并获取 largestsmallest 元素呢?这样,您的索引和值都会有最大的差异。您当前方法的时间复杂度至少 O(n^2),假设append 摊销O(1)。排序方法为O(n log n)
  • 您还需要考虑索引(在排序之前),但是是的,这些方面的东西是您真正节省时间的方式。
  • @meowgoesthedog 感谢您将排序纳入图片。一个问题我如何知道何时使用编程语言或 DS 或 ALGO 的哪些功能?它来自经验吗?

标签: python algorithm optimization data-structures


【解决方案1】:

对于给定的j<=i|a[i]-a[j]|+|i-j| = max(a[i]-a[j]+i-j, a[j]-a[i]+i-j)

因此对于给定的i,最大化|a[i]-a[j]|+|i-j|j<=i 的值要么是最大化a[j]-jj,要么是最小化a[j]+jj

这两个值都可以在你沿着数组运行时计算出来,给出一个简单的 O(n) 算法:

def maxdiff(xs):
    mp = mn = xs[0]
    best = 0
    for i, x in enumerate(xs):
        mp = max(mp, x-i)
        mn = min(mn, x+i)
        best = max(best, x+i-mn, -x+i+mp)
    return best

下面是针对一个幼稚但明显正确的算法的一些简单测试:

def maxdiff_naive(xs):
    best = 0
    for i in xrange(len(xs)):
        for j in xrange(i+1):
            best = max(best, abs(xs[i]-xs[j]) + abs(i-j))
    return best

import random

for _ in xrange(500):
    r = [random.randrange(1000) for _ in xrange(50)]
    md1 = maxdiff(r)
    md2 = maxdiff_naive(r)
    if md1 != md2:
        print "%d != %d\n%s" % (md1, md2, r)
        exit

在大小为 10^5 的数组上运行 maxdiff 只需几分之一秒,这明显优于您报告的排行榜得分。

【讨论】:

  • 感谢您的洞察力,我从不知道枚举具有如此强大的功能。将每个测试用例的时间从 10 秒减少到 6 秒
  • 如果约束如您在问题中描述的那样,测试用例不可能花费长达 6 秒的时间。你用的是maxdiff,还是测试代码?
  • 排行榜上没有提到的单位只有6我使用了maxdiff。如上所述,测试用例的数量也很大。
【解决方案2】:

“竞争性编程”不是通过使用不同类型的循环来节省几毫秒;这是关于如何聪明地解决问题,并然后有效地实施解决方案。

不过,跳出来的一件事是,您正在浪费时间建立一个列表,只是为了扫描它以找到最大值。您的双循环可以转换为以下内容(忽略其他可能的改进):

print(max(abs(a[s] - a[d]) + abs(s - d) for s in range(n) for d in range(n)))

但这只是小菜一碟。首先担心你的算法,然后然后转向像这样明显浪费时间的东西。正如@Brett 向您展示的那样,您可以将比较次数减少一半,但我会首先研究这个问题并问自己:我真的需要计算这个数量n^2 次,甚至0.5*n^2 次吗?这就是您缩短时间的方法,而不是通过减少毫秒。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-27
    • 2020-05-18
    • 1970-01-01
    • 1970-01-01
    • 2021-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多