具体数学 - 和式与递归式 Sums and Recurrence
基于一些和式计算的特殊方法,在将递归式转换为和式后,可以简化递归式的求解。
使用和式求解汉诺塔问题
考虑汉诺塔问题的递归关系:
等式两边同时除以 \(2^n\),得
令 \(S_n = T_n/2^n\), 有
由此得到
因此 \(T_n = 2^nS_n = 2^n-1\)。上述过程的核心思想在于,利用一个求和因子在等式两边相乘。对于形如 \(a_nT_n=b_nT_n+c_n\) 的递归关系,求和因子 \(s_n\) 满足 \(s_nb_n=s_{n-1}a_{n-1}\),从而得到递归式
则 \(T_n = \frac{1}{s_na_n}(s_1b_1T_0 + \sum_{k=1}^{n}s_kc_k)\)。那么我们如何求出 \(S_n\) 呢?我们根据 \(s_n=\frac{a_{n-1}}{b_n}s_{n-1}\) 进行展开,发现求和因子 \(s_n = \frac{a_{n-1}a_{n-2}\dots a_1}{b_nb_{n-1}\dots b_2}\) 或为其整数倍时容易求解,如汉诺塔问题中的 \(a_n=1, b_n=2, s_n=2^{-n}\)。注意该分式的分母不能包含零项。
使用和式求解快速排序比较次数问题
快速排序算法的平均比较次数 \(C_n\) 满足递归式
首先我们使用 \(n\) 乘以等式两边,得
然后我们使用 \(n-1\) 替换上式中的 \(n\),得
最后两式相减以消除和式,有
我们得到化简后的递归式
将前述的一般形式递归关系求解方法代入,得
使用和式求解Top-K比较次数问题
我们可以参考快速排序的思想,在一个长度为 \(n\) 的序列中选择出第 \(K\) 大的元素,其比较次数为\(C_n\)。该算法的伪码如下所示。
int partition(int a[], int start, int end) {
int key = a[start];
while (start < end) {
// largers on the left.
while (start < end && a[end] <= key)
end--;
if (start < end) {
swap(a[start], a[end]);
}
// smallers on the right.
while (start < end && a[start] > key)
start++;
if (start < end) {
swap(a[end], a[start]);
}
}
a[start] = key;
return start;
}
int kth_qsort(int a[], int start, int end, int k) {
int pivot = -1, len = 0;
if (start < end) {
pivot = partition(a, start, end);
len = pivot - start + 1;
if (len < k) {
pivot = kth_qsort(a, pivot + 1, end, k - len);
} else if (len > k) {
pivot = kth_qsort(a, start, pivot - 1, k);
}
}
return pivot;
}
int kth_top(int a[], int k) {
int p = kth_qsort(a, 0, N, k);
return a[p];
}
对于一次长度为 \(n\) 的递归过程,枢纽变量需要与其他元素进行 \(n\) 次比较。下一次递归过程只需要对枢纽变量一侧的序列进行处理,序列长度为 \(i\) 的概率为 \(\frac{1}{n}\),比较次数为 \(c_i\)。因此,在长度为 \(n\) 的序列中找出第 \(K\) 大个元素所需的总比较次数满足的递归关系为
等式两边同乘以 \(n\),得
使用 \(n-1\) 代替 \(n\),得
两式相减以消去和式,有
化简得到递归关系
直接展开
调和级数
上述过程提及的级数 \(H_n = \sum_{i=1}^{n}\frac{1}{i}\) 称为调和级数,其计算时间复杂度推导如下。

浙公网安备 33010602011771号