【问题标题】:Analyzing a stack sort algorithm's time complexity分析堆栈排序算法的时间复杂度
【发布时间】:2017-01-24 05:42:18
【问题描述】:

我一直在解决破解编码面试中的问题,为一些面试做准备。我能够解决堆栈排序问题,但我很难弄清楚如何推理时间复杂度。我的解决方案与书中提供的解决方案非常相似,并且我已经对其进行了相当多的测试,所以我确信它是正确的。任何对分析该算法的思考过程的见解将不胜感激。这本书说它是O(n ^ 2)。这是算法:

def sort_stack(stack):
    temp_stack = Stack()
    while not stack.is_empty():
        v = stack.pop()
        if temp_stack.is_empty() or temp_stack.peek() <= v:
            temp_stack.push(v)
        else:
            while not temp_stack.is_empty() and temp_stack.peek() > v:
                stack.push(temp_stack.pop())
            temp_stack.push(v)
    while not temp_stack.is_empty():
        stack.push(temp_stack.pop())

附带说明:我使用这种方法对堆栈进行排序,以便在问题的约束范围内。我知道存在更快的解决方案。

提前谢谢你。

【问题讨论】:

  • 外循环至少有 n 次迭代,我知道。内部循环可能有 0 和 temp_stack.size 之间的迭代,具体取决于值。在最坏的情况下,原始堆栈已经排序,我们将有 0 + 1 + 2 + 3 + ... (n -1) 次迭代......但我认为总和最终为 n(n + 1) / 2 当我们忽略本身为 n^2 的常量时。我以为我在做某事,但现在我不确定。
  • 或者内部循环的分析是:1/n + 2/n + 3/n + 4/n + .... (n-1)/n 我们认为只是吗?时间不早了,我要睡觉了>.

标签: python algorithm sorting stack big-o


【解决方案1】:

考虑最坏的情况,对堆栈中的每个项目进行排序需要完全清空临时堆栈。 (尝试对反向排序的堆栈进行排序时会发生这种情况。)

清空/重新填充每个项目的临时堆栈的成本是多少?
有多少项?

结合这些应该得到 O(n^2)。

【讨论】:

  • 第 1 项需要 0 次临时堆栈弹出,第 2 项需要 1 次弹出,第 3 项需要 2 次弹出……第 n 项需要 n-1 次弹出。所以总共我们有 1 + 2 + 3 + 4 + 5 + ..... + N 次内循环迭代。也就是说,N(N+1)/2 或 1/2(N^2 + N),即 O(n)。我认为当在求和过程中已经考虑到外循环时,我正在错误地将 N 再次乘以外循环。我一直得到 O(N^3)。
  • 是的,该总和已经计算了临时堆栈弹出的总数。尽管它不包括将“已见”项目推回临时堆栈,但将工作加倍以包含它并不会改变整体复杂性。从逐行分析代码后退一步,我是这样想的:您看到的每个新项目都需要 O(n) 弹出/推送才能将其插入临时堆栈。重复此 n 次会导致 O(n^2)。
  • 感谢您指出推送。起初我不认为他们会加倍工作,但后来我意识到我必须再次推动每一个流行音乐!我理解您的观点,尽管在渐近分析中将工作加倍不会影响我们的整体复杂性。谢谢你的时间:)
【解决方案2】:

这可能是一种过于简化的算法分析方法,但每当我看到嵌套循环时,我都会想到 n^2。三个嵌套循环——n^3 等。作为简单程序的经验法则,计算嵌套循环。这是一个非常有用的教程:http://cs.lmu.edu/~ray/notes/alganalysis/

【讨论】:

  • 这在很多情况下确实有效,但我同意这是一种过于简单的方法。这本书指出,记住你提到的“模板”并不是一个深刻的理解。感谢您的意见!