双不变for循环的时间复杂度

Time complexity of double invarient for loops

我有一个列表数组(即数组中的每个单元格都包含一个列表)。数组的长度为n,所有列表的所有长度之和为k

我想遍历所有列表元素(在整个数组中):

for(int i = 0; i < n; ++i) {
    for(int j = 0; j < array[i].list.Length(); ++j) {
        //do something in O(1)
    }
}

注意 每次外循环迭代运行的内循环少于 k 次,但它对所有 i 执行的总迭代次数是 k

问题代码的时间复杂度是O(n + k)吗?还是 O(n*k)?

你应该使用n*k。

Foreach cols, process each lines.

您必须对每一列 (n) 执行循环(for 或 foreach)。
然后在 n 循环内,您执行另一个循环(for 或 foreach)来处理每一行 (k)。

for (int i = 0; i < n; i++) {
   for (int j = 0; j < array[i].list.length(); j++) {
     // do something with array[i][j]
   }
}

对于外部循环的每个 i,内部循环是 运行 array[i].list.Length() 你说的是 k:

k times + -+
k times +  |
...        |
...        +--- n times
...        |
k times   -+

所以得到的时间是O(n * k)

Question Does the time complexity of the code is O(n + k)? Or would it be O(n*k)?

都没有。

复杂度为O(n + k)。在 n <= k 的情况下,这将等于 O(k),但情况不一定如此。

n <= k(原始答案)

如果所有长度的总和是k,那么,如果你在外循环中不做任何其他事情,运行时间就是O(k)n 在这种情况下无关紧要,因为您所做的 n 次没有任何有趣的事情。您的数据恰好被分成 n 个块。

平均而言,每个列表的大小为 k/n。这使得算法的时间复杂度 O(n * k/n) 导致 O(k).

n > k

n 大于 k 的情况下,n 变得相关,因为每次都必须完成工作,即使它只是检查 Length() array[i]。因此,在这种情况下,复杂度为 O(n + k).

更新

正如 Jordi Vermeulen 在评论中正确指出的那样,我最初的回答只考虑了 n <= k 不完整 的情况。答案已相应编辑。

这是O(n + k),当n为O(k)时为O(k)。然而,情况不一定如此(正如 Bart van Nierop 在回答中所建议的那样)。例如,考虑 n = k2 的情况。循环仍然是 运行 k2 次,所以你不能说复杂度是 O(k),即使在许多迭代中除了增加之外不会做任何工作柜台.

O(k).do something part 会出现 k 次。 n 在这种情况下无关紧要。