注:2019-09-09,我的学习路程真是挺好玩,半路折回来要补一补算法知识。
为了提高效率,选择了北大数据结构与算法公开课,而不是自学或者好评更多的其他国外课程【听力比教差,费劲且没必要】
1,数字三角形问题
因为是学习日志,这里不做介绍,只写代码【cpp/python】。建议看到我博客的倒霉蛋,直接去课程听讲 点这里
1-1:基于深度优先的普通递归
复杂度:0( 2 n 2^n 2n) 很差,递归涉及到了大量的重复计算
#include<algorithm>
#define MAX 101
using namespace std;
int D[MAX][MAX];
int n;
int MaxSum(int i, int j){
if (i == n)
return D[i][j];
int maxa = MaxSum(i, j);
int maxb = MaxSum(i, j+1);
return max(maxa, maxb) + D[i][j];
}
int main(){
int i, j;
cin n;
for (i=1; i<=n; i++)
for (j=1; j<=i; j++)
cin >> D[i][j];
cout << MaxSum(1, 1) << endl;
return 0;
}
1-2 动态法【添加额外数组进行存储】
复杂度:0(
n
2
n^2
n2)
这里回想一下大一寒假在小甲鱼那初学python的时候,一道比较难的课后习题,我就是使用了额外数组保存的方法,当时印象很深。所以一直有种感觉,很多知识你其实是知道的,之前也是不经意间用过,而系统的学习这些课程,会给你一种 this feeling i can not describe…
代码改进:
注意:maxSum的元素是当前位置遍历到最后一行的值!(深度优先)
int D[MAX][MAX];
int maxSum[MAX][MAX]; // 改动
int n;
int MaxSum(int i, int j){
if (maxSum[i][j] != -1) //改动
return maxSum[i][j]; // 因为已经计算过,直接返回
if (i == n)
return D[i][j];
int maxa = MaxSum(i, j);
int maxb = MaxSum(i, j+1);
return max(maxa, maxb) + D[i][j];
}
int main(){
int i, j;
cin n;
for (i=1; i<=n; i++)
for (j=1; j<=i; j++)
cin >> D[i][j];
maxSum[i][j] = -1; // 改动,初始化所有结果皆为-1,方便后面函数判断
cout << MaxSum(1, 1) << endl;
return 0;
}
可以看出,以空间复杂度为代价优化了时间复杂度,不过并不亏
2 递推法
递归这玩意,… 不多说了,装哔小能手吧
递推主要思想:自底向上计算,因为如果按照自顶向下会有很多分叉,根本无法递推实现,或者又要走重复计算的老路子
我直接截图了,老师对不起
代码(个人),初学cpp,最好别看:
#define MAX 101
using namespace std;
int D[MAX][MAX];
int maxSum[MAX][MAX];
int n;
// 递推-自底向上
int MaxSum(int D[][], int maxSum[][], int n){
for (i = n-1; i>=1; --i)
for (j = 1; j<=n; ++j)
if (i == n)
maxSum[i][j] = D[i][j];
else
maxSum[i][j] =
max(maxSum[i+1][j], maxSum[i+1][j+1]) + D[i][j];
return maxSum[1][1];
}
int main(){
int i, j;
cin >> n;
// 初始化数字三角形
for(i=1; i<=n; i++)
for (j=1; j<=i; j++)
cin >> D[i][j];
cout << MaxSum(D, maxSum, n) << endl;
return 0;
}
3结合指针递推
优化空间,时间复杂度不变
主要是,不再额外的创建二维数组来保存结果,因为是自底向上的原因,下面一行在计算之后就不再使用,所以没必要保存,所以这里将三角形的底边作为存储的地方,并且不影响结果【每次的结果都保存在底边】,实现了 时间,空间的优化
# define Max 101
int main()
{
int D[Max][Max];
int n;
int * maxSum;
cin >> n;
for (int i=1; i<=n; i++)
for (int j=1; j<=i; j++)
cin >> D[i][j];
maxSum = D[n]; // maxSum指针定位到D的第n行
for (int i=n-1; i>=1; --i)
for (int j=1; j<=i; ++j)
maxSum[j] = max(maxSum[j], maxSum[j+1]) + D[i][j];
cout << maxSum[1] << endl;
return 0;
}
4 python版
写到最后怎么能少得了我的母语呢 :)
import numpy as np
D = np.random.randint(10, size=(5, 5)).tolist() #随机初始化矩阵
D = np.tril(D, 0) #设置为下三角矩阵
for i in range(len(D)-2, -1, -1): # 直接在原矩阵上计算
for j in range(i+1):
D[i][j] = max((D[i][j]+D[i+1][j]), (D[i][j]+D[i+1][j+1]))