【问题标题】:Python3 Loop: Time limit exceeded, Code OptimizationPython3 循环:超出时间限制,代码优化
【发布时间】:2021-09-26 16:15:22
【问题描述】:

我正在尝试通过在 HackerRank.com 上解决简单的数据结构问题来学习 Python。我试图解决Left Rotation 挑战:

对大小为 ???? 的数组的左旋转操作将每个 数组的元素向左 1 个单位。给定一个整数 ????, 将数组旋转剩下的步数并返回结果。

示例

???? = 2
???????????? = [1, 2, 3, 4, 5]
2 次旋转后,???????????? = [3, 4, 5, 1, 2].

我建议了以下解决方案。它适用于 8 个用例,但在最后两个用例中出现超时错误。

def rotateLeft(d, arr):
    new = arr[0:]
    for _ in range(d):
        i, new = new[0], new[1:]
        new.append(i)
    return new

我不是在寻找一些基于公式的单线解决方案。我知道它可以解决手头的问题,但它无法帮助我理解如何优化基于循环的简单解决方案。

我正在寻找优化规则,对于这个问题和一般的问题。

【问题讨论】:

  • 如何摆脱循环并使用切片一次性执行所有旋转?比如例子是arr[2:] + arr[:2]
  • d 是一个变量,因为 slicing solution 只有在 d=4 时才有效。
  • 当然你为d的不同值做了不同的切片。

标签: python-3.x loops optimization


【解决方案1】:

当您意识到d 可能比列表的大小大很多倍时,优化是可能的。在这种情况下,您将浪费时间轮换列表,只是将其多次恢复到原来的顺序以最终达到预期的轮换。

所以只执行d % len(arr) 旋转。

第二个优化是您实际上不必逐个执行旋转。您可以通过从左侧切分许多值(在一次操作中)并将它们附加到右侧(在一次操作中)来一次性完成d % len(arr) 旋转。这样你的代码甚至不会有一个显式循环。

所以在 Python 中这很容易:

def rotateLeft(d, arr):
d %= len(arr)
return arr[d:] + arr[:d]

如果您想通过一次移动一个值来完成此操作,而不进行切片或列表解析,请按以下步骤操作:

def rotateLeft(d, arr):
    result = []
    for i in range(len(arr)):
        result.append(arr[(i + d) % len(arr)])
    return result

...但这不是那么有效。切片是 Pythonic 的方式。

【讨论】:

  • 我尝试将轮换限制为d % len(arr),但如前所述,最后两个案例都失败了。
  • 你也应该使用第二个优化。
  • 它有效,但是先生,如果我可以问你(因为你看起来很专业)为什么这个问题得到负面评价?即使你(有这么多评价)一开始也无法给出正确的“循环”答案,这也是一个合法的问题。似乎这里没有人理解这个问题并继续投票,除非它是一些“jarvis”级别的东西。我的意思是优化循环而不知道替代解决方案,您的第一个答案 (So only perform d % len(arr) rotations) 非常相关,但它当然没有用。
  • 我没有投反对票,但短语 “我不是在寻找一些基于公式的单线解决方案。我知道它会解决问题” 可以敦促一些人人们投反对票的原因如下:(1)许多人不喜欢人为的限制:我们想在我们的答案中推广最佳实践,而这种限制迫使人们用劣质的解决方案来回答。这是不受欢迎的。 (2)既然你建议有工作代码,真的没有问题了。最后,我最初的回答没有提供完整的代码,因为我们认为提问者应该努力。
  • 顺便说一句,如果你找到了答案,你还有一件事要做……别忘了mark an answer as accepted。如果您重写令人不安的段落(请参阅我之前的评论),那么我会支持您的问题。如您所见,我已经尽力改进您问题的格式。
【解决方案2】:

提供的解决方案的问题在于它会分配大量内存。每次调用new.append(...) 时,程序都需要检查它是否有足够的内存分配来将提供的元素添加到列表的末尾。如果没有足够的分配内存,程序需要分配一个新的更大的内存块并将所有现有数据复制到新位置。这一切都需要很多时间。为了优化它,请考虑一种解决方案,您可以更改列表元素的值,而不是删除和添加元素。这将减少内存重新分配的次数。

我不会为上述问题提供解决方案,因为我认为这样做的全部目的是锻炼作者的编码技能。

【讨论】:

    猜你喜欢
    • 2021-08-09
    • 1970-01-01
    • 2011-03-12
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多