问题描述
我之前有以下问题:
注意: k 是常数且 3,对于 n, T(n)=0。
我该如何解决这样的问题?
解决方法
好吧,我不会展示我所有的步骤。这是您的家庭作业问题,但这里有一个概述:
-
基于递归定义,我们可以分解求和:
T(n) = n + T(floor(n / k)) + T(floor(n / k ^ 2)) + ... + T(floor(n / (k ^ log(n))))
-
那么由此,我们可以得到一个迭代定义:
T(n) = n + floor(n / k) + 2 * floor(n / k ^ 2) + ... + 2 ^ (log(n) - 1) * floor(n / k ^ (log(n)))
或
T(n) = n + Sum( floor(n / k ^ i) * 2 ^ (i),i=1,log(n) ) / 2
您的问题需要大 Theta。这意味着我们需要找出一个上限和下限。
-
上限:
floor(x) <= x
,所以我们放下地板并简化:O( n + n / (k - 2) <-- O(n) + (n * (2 / k) ** log(n)) / (k - 2) )
因为
k > 3 > 2
,最后一项保证增长小于n
,所以我们剩下O(n)
。 -
下限:总是
Sum(...) > 0
,所以我们可以只用n
将其绑定在下面,给出Omega(n)
。
因为T
对于O(f(n))
既是Omega(f(n))
又是f(n) = n
,所以我们可以说它也是Theta(n)
,所以答案是
f(n) = n
这是一个演示上限和下限的程序。该程序不等同于证明,但它可以帮助您了解正在发生的事情。我以指数方式增长 n
,因此如果您在对数刻度上绘制值,它应该显示线条和渐近行为。
const k = 4;
const logK = Math.log(k);
function T(n) {
if (n <= 1)
return 0;
let acc = n;
for (let i = 1; i <= Math.log(n) / logK; i++)
acc += T(Math.floor(n * k ** -i));
return acc;
}
function nonRecT(n) {
let acc = n;
for (let i = 1; i <= Math.log(n) / logK; i++) {
let f = Math.floor(n * k ** -i);
acc += f > 1 ? f * 2 ** (i - 1) : 0;
}
return acc;
}
for (let n = k; n <= k ** 20; n *= k) {
console.log([
n,T(n),nonRecT(n),n * (1.5 + 1 / (k - 2))
].join('\t'));
}