【问题标题】:Nested time complexity嵌套时间复杂度
【发布时间】:2014-06-02 18:00:08
【问题描述】:

我希望这是一个简单的问题,但 Google 并没有立即给我任何结果。

如果我有一个运行时间为 O(n log n) 的函数,并且该函数内部是另一个函数,也是 O(n log n),那么该函数的总运行时间是多少?

假设我有一个列表列表。

需要 n log n 时间才能找到所需的列表,然后再次 n log n 时间才能在该列表中找到所需的项目。

类似

find list in n log n time
     find element in list in n log n time

运行时间还只是n log n吗?

提前谢谢你。

如果函数如下所示:

for each element e1 in list                          // (O(N) time)  
    if e1 is the one we are looking for  
        for each element e2 in e1                    // (O(N) time)  
            do something

O(N)里面是O(N),但是第二个O(N)在第一个循环中只执行一次。

【问题讨论】:

    标签: performance algorithm time-complexity


    【解决方案1】:

    这取决于你调用第二个函数的频率。

    如果您执行一个函数,该函数在 O(n log n) 时间内在列表列表中找到一个列表 然后在仅一个列表中搜索所需的元素,它在 O(m log m) 时间内找到, 那么总运行时间为 O(n log n + m log m)。
    如果 m=n 那么总时间就是 O(n log n)。

    如果外部循环执行 O(n log n)“步骤”,并且在每个步骤中,您从列表列表中考虑一个列表并调用一个函数,该函数需要 O(m log m) 时间来找到所需的项目该列表,则总运行时间为 O(mn (log m)(log n))。但是,我很难想象哪个应用程序会使用这样的算法。

    如果你执行一个循环 O(N) 次,并且在循环的最多 一个 次迭代中你执行一个在 O(M) 时间内运行的“内部”循环,那么外循环的总运行时间为 O(N + M)。请注意,我们说 O(M + N) 的原因是我们没有 本段中关于增长更快的任何其他信息,M 或 N,以及 O(M + N) 在任何一种情况下都涵盖我们。同样,如果我们知道 M=N,或者即使我们只知道 M 是 O(N)(不会比 N 增长得快),那么我们可以将总时间写为 O(N)。

    【讨论】:

    • 谢谢!这很有意义。也感谢 Mooing Duck。你的评论也很有帮助。我正在尝试使用 List of Lists 方法制作稀疏矩阵。第一个列表包含具有 X 坐标和相关 Y 坐标和值的列表的元素。为了找到一个元素,我遍历 X 坐标列表以找到我正在寻找的元素。找到后,我会迭代所有关联的 Y 坐标以找到正确的。
    • 假设我有一个包含 N 个列表的列表。我通过 O(N) 时间的线性搜索找到了我正在寻找的列表。找到的列表有 M 个元素。我现在在 O(M) 时间内对该列表进行线性搜索。总时间是O(N+M)吗?如果使用二分搜索需要 O(log N) 和 O(log M) 才能找到它们会怎样。总时间会是 O(log N + log M) 吗?
    • @JacobOJ:是的,没错。 DavidK:您的回答被原始发帖人使用n 代表两个不相关的值这一事实误导了。
    • 当我写下我的答案时,我想知道我是否应该只使用 N (如问题中所示)或者我是否应该将 M 用于一个循环,而将 N 用于另一个循环(从而提供更普遍有用的回答)。回想起来,我认为我应该使用 M 和 N,所以我已经相应地编辑了答案。
    【解决方案2】:

    嗯,从数学上讲,您只需将“里面的内容”乘以大 Os。你得到O(n² log²(n))

    【讨论】:

    • 你会这样做,而不是在 nlogn 中替换每个 n 这本来是我的直觉......
    • 我们写两个算法的复杂度T1(n)T2(n)。按照您的方式,它们的嵌套复杂性将是T1(T2(n))。让我们检查一下。使用T1(n) = T2(n) = n(嵌套循环),您可以获得整体复杂性:T1(T2(n)) = T1(n) = n。我们知道嵌套循环会产生 ,所以你的方法是错误的 ;-) (是的,我知道从技术上讲,我只是证明你的方法行不通, 不是 我的是正确的,但我不是数学家)
    • 是的,这是有道理的。我的直觉是说 T1(T2(n)) 但你是对的,你已经证明那是垃圾。除了您的选择之外,我想不出任何其他选择,但遗憾的是,我不知道您是对的,所以不能凭良心为您 +1。 :(
    • 如果函数看起来更像这样:pastebin.com/TjR38V06 时间复杂度是多少?它
    • 我认为问题在于一个是n*log(n),另一个是n*log(n),而_这两个n是完全不相关的。更准确的说法是内循环是m*log(m),整体算法是O(n*m*log(n)*log(m))
    【解决方案3】:

    你的符号掩盖了事实,没有“另一个函数”。 (更准确地说,没有函数会调用另一个多次。)

    实际做的是

    find list in n log n time;
    
    find element in list in n log n time
    

    复杂度为 n log n。

    在第二个例子中:

    for each element e1 in list                   // (O(N) time)  
        if e1 is the one we are looking for 
            break // Found
    
    for each element e2 in e1                    // (O(N) time)  
        do something
    

    总共 O(N)。

    这与真正的嵌套形成对比:

    for each element e1 in list                      // (O(N) passes)  
        for each element e2 in e1                    // (O(N) time)  
            do something
    

    总共 O(N²)。

    【讨论】:

    • 您的符号也很麻烦,因为它将 e1 视为一个元素和一个列表。
    • 是的,很抱歉。 E1 是一个包含列表的元素。
    • 原始发帖人使用n 表示两个不相关的值也误导了这个答案。
    【解决方案4】:

    对于

    find list in n log n time
         find element in list in n log n time
    

    我们得到

    Time = n log n * n log n = 2 n log n ~ O(n log n)
    

    对于

    for each element e1 in list                   // (O(N) time)  
        if e1 is the one we are looking for  
            for each element e2 in e1             // (O(N) time)  
                do something
    

    我们得到

    Time = n + k n = (k+1) n
    
    Best-Case: only 1 matching value exist
    
    Time(Best-Case) = n + 1 * n = 2n ~ n
    
    Worst-Case: all values are identical and matching
    
    Time(Worst-Case) = n + n * n = n + n^2 ~ n^2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-27
      • 2019-05-18
      • 2021-11-14
      • 1970-01-01
      相关资源
      最近更新 更多