带记忆的循环内递归的运行时复杂度
Runtime complexity of recursion inside loop with memoization
我想知道如何确定以下代码的时间复杂度,使用带记忆的自顶向下动态规划方法(注意 i、k、d 可以是任何整数值):
solve(i, k, d) {
if (k >= d) {
A[i][k] = 0;
return 0;
}
if (i == 0) {
A[i][k] = 0;
return 0;
}
if (A[i][k] == null) {
for (int j = 0; j < k + 1; j++) {
A[i][k] = solve(i - 1, (k + 1 - j), d);
}
}
return A[i][k];
}
问题 :
solve(i - 1, (k + 1 - j), d)
当 j = 0 时会给出越界错误,因为 A
索引应该从 0 到 K [K 是最大索引]
答案:该函数的复杂度为 O(n * n)。
直觉:
(很明显,最坏的情况是没有解决方案,所以我专注于此)
由于递归调用是在将值放入记忆缓存之前进行的,因此最后(最短)的后缀将首先被缓存。这是因为该函数首先使用长度为 N 的数组调用,然后使用长度为 N-1 的数组调用自身,然后......,使用缓存的 len 0 数组 returns,则缓存长度为1的数组并returns, ...,缓存长度N并returns.
解释:
假设矩阵的大小为 I x K 并考虑最坏情况,
[注意] 在最坏的情况下,函数调用将从矩阵的右下角开始
A
初始化发生在两种情况下:
k >= d
i == 0
[注意] 在最坏的情况下,k
总是小于 d
。
For loop for `(I, K)`
- Recursion call `for (i-1, k:[K to 0])`
- Update value for `A[i, k]`
[注意] i = 0 是函数初始化时的基本情况 A
和 returns 0.
我想知道如何确定以下代码的时间复杂度,使用带记忆的自顶向下动态规划方法(注意 i、k、d 可以是任何整数值):
solve(i, k, d) {
if (k >= d) {
A[i][k] = 0;
return 0;
}
if (i == 0) {
A[i][k] = 0;
return 0;
}
if (A[i][k] == null) {
for (int j = 0; j < k + 1; j++) {
A[i][k] = solve(i - 1, (k + 1 - j), d);
}
}
return A[i][k];
}
问题 :
solve(i - 1, (k + 1 - j), d)
当 j = 0 时会给出越界错误,因为 A
索引应该从 0 到 K [K 是最大索引]
答案:该函数的复杂度为 O(n * n)。
直觉:
(很明显,最坏的情况是没有解决方案,所以我专注于此)
由于递归调用是在将值放入记忆缓存之前进行的,因此最后(最短)的后缀将首先被缓存。这是因为该函数首先使用长度为 N 的数组调用,然后使用长度为 N-1 的数组调用自身,然后......,使用缓存的 len 0 数组 returns,则缓存长度为1的数组并returns, ...,缓存长度N并returns.
解释:
假设矩阵的大小为 I x K 并考虑最坏情况,
[注意] 在最坏的情况下,函数调用将从矩阵的右下角开始
A
初始化发生在两种情况下:
k >= d
i == 0
[注意] 在最坏的情况下,k
总是小于 d
。
For loop for `(I, K)`
- Recursion call `for (i-1, k:[K to 0])`
- Update value for `A[i, k]`
[注意] i = 0 是函数初始化时的基本情况 A
和 returns 0.