前言
本笔记为仅为本人读《算法导论(第三版)》时的个人理解与感想,非教程解读。如有疏漏错误,还望海涵。
第三章 函数的增长
当输入规模足够大,使得只有运行时间的增长量级有关时,提出我们要研究渐近效率
渐近记号
Θ记号,运行时间函数的上下界;
Ο记号,渐近上界,被Θ记号包涵,不一定是确界,多指最坏运行时间;
Ω记号,渐近下界,被Θ记号包涵,不一定是确界,多指最好运行时间;
渐近上/下界用于确定函数的渐近确界(高等数学-夹逼定理);
ο记号,类似于等价无穷小,非渐近上界;
ω记号,类似于等价无穷大,非渐近下界;
以上函数记号具有:
- 传递性
- 自反性
- 对称性
- 转置对称性
- 三分性
常用数学概念
略
第四章 分治策略
该策略下,递归地求解一个问题,分为:分解(Divide)、解决(Conquer)、合并(Combine)三步。
递归式 为分策略的基础
递归式求法:
- 代入法
- 递归树法
- 主方法
T(n) = aT(n / b) + f(n)
其中a >= 1, b > 1
最大子数组问题
暴力求解方法: 每对下标的组合Ω(n²)
;
问题变换为——第 i 个的数值变化为第 i 个和第 i - 1 个的数值差;
重新组织计算方式为——利用之前计算出的子数组的和来计算当前子数组的和;
使用分治策略的求解方法:
int[] netWorth(int[] A) {
int[] B = new int[A.length - 1];
for(int i=0;i<A.length-1;i++){
B[i]=A[i+1]-A[i];
}
return B;
}
//处理中间情况
int[] findMaxCrossingSubarray(int[] A, int low, int mid, int high) {
int sum = 0;
//先处理左侧
float sumL = Float.NEGATIVE_INFINITY;
int maxL = mid;
for(int i = mid; i >= low; --i) {
sum += A[i];
if(sum > sumL) {
sumL = sum;
maxL = i;
}
}
sumL = (int)sumL;
//再处理右侧
sum = 0;
float sumR = Float.NEGATIVE_INFINITY;
int maxR = mid;
for(int i = mid + 1; i <= high; ++i) {
sum += A[i];
if(sum > sumR) {
sumR = sum;
maxR = i;
}
}
sumR = (int)sumR;
int[] res = {maxL, maxR, (int)(sumL + sumR)};
return res;
}
int[] findMaxSubarray(int[] A, int low, int high) {
int[] res;
if(high == low) {
res = new int[] {low, high, A[low]};
return res;
}
else {
int mid = (low + high) / 2;
int[] L = findMaxSubarray(A, low, mid);
int[] R = findMaxSubarray(A, mid + 1, high);
int[] C = findMaxCrossingSubarray(A, low, mid, high);
if(L[2] >= R[2] && L[2] >= C[2]) {
res = L;
}
else if(R[2] >= L[2] && R[2] >= C[2]) {
res = R;
}
else {
res = C;
}
return res;
}
}
输入数组需经过netWorth()
函数转换为净值,然后使用findMaxSubarray()
得出结果;
矩阵乘法的Strassen算法
数学思想:
代码如下:
int[][] squareMatrixMultiplication(int[][] A, int[][] B){
int[][] C = new int[A.length][B[0].length];
for(int i = 0; i < A.length; ++i) {
for(int j = 0; j < B[0].length; ++j) {
for(int k = 0; k < B.length; ++k) {
C[i][j] += A[i][k] * B[k][j];
}
}
}
return C;
}
时间复杂度为Θ(n³)
分治思想:
书中提到关键问题为分解矩阵,入社划分子矩阵,复制元素会花费Θ(n²)
时间复制元素,但对总渐近运行时间Θ(n³)
并无影响;
可以使用下标计算来分解矩阵;
将矩阵划分为四个规模相同的单元,进行最简单矩阵乘法,然后合并,仅适用于方阵;
书中伪代码过于抽象;
论坛中给出的是想方式,非常复杂;
综上,非必要使用正常方法即可;
时间复杂度为Θ(n³)
Strassen方法:
神仙数学家使用某种奇妙数字组合使矩阵运算由8次乘法变为7次乘法,时间复杂度下降,即:
正常递归方法:
r = ae + bg
s = af + bh
t = ce + dh
u = cf + dg
共8次乘法;
大佬改进方法:
P1 = a * (f - h)
P2 = (a + b) * h
P3 = (c + d) *e
P4 = d * (g - e)
P5 = (a + d) * (e + h)
P6 = (b - d) * (g + h)
P7 = (a -c) * (e + f)
r = P5 + P4 - P2 + P6
s = P1 + P2
t = P3 + P4
u = P5 + P1 - P3 - P7
实现:
参考:https://blog.csdn.net/dawn_after_dark/article/details/78686488
递归式求法及递归树画法
暂时没有需求,略;
第五章 概率分析和随机算法
雇佣问题:
- 生日悖论
- 球与箱子
- 特征序列
- 在线雇佣问题
总结&心得
1、怀疑我看了盗版书,这翻译怎么感觉像机翻的;
2、简单的线性代数骗我说是解方程的我信了,那一些高级的概念呢?太抽象了哇,数学家都是神仙;
3、了解了概率分析在计算机学科上的应用,猜测可能与数据分析有关;