目录
前言
问题描述
解决思路
代码实现(C语言)
1.递归算法
2.递归优化(输出路径)
3.非递归算法(输出路径)
今天我们接着解决一个问题,也就是求数字三角形路径最大的问题,下面我会详细讲解这个问题的解决思路,以及通过代码的方式去解决这个问题,下面接着看。
给出了一个数字三角形,从三角形的顶部到底部有多条不同的路径。 对于每条路径,把路径上面的数加起来可以得到一个和,累加和最大的路径称为“最佳路径”。
样例输入:
第一行是数塔层数N(1<=N<=100)。
第二行起,从一个数字按数塔图形依次递增,共有N层。
5
13
11 8
12 7 26
6 14 15 8
12 7 13 24 11最大路径输出结果:86
对于这一类问题我们很容易想到去通过递归的方式来解决,先创建一个二维数组来储存这些数据, 然后去通过递归比较大小,取其中比较大的进入到下一层递归,也就是当前节点加上其左边和右边节点较大者。
#include
#include
//比较获取最大值
int max(int a, int b) {
return a > b ? a : b;
}
//递归函数
int fun(int n, int i, int j, int** a) {
//如果递归到最上一层的话就直接返回0即可
if (i == n) {
return 0;
}
//进入到递归,当前数字加上左右两边的较大者
return a[i][j] + max(fun(n, i + 1, j, a), fun(n, i + 1, j + 1, a));
}
int main()
{
int n;
printf("enter your num:");
scanf("%d", &n);
//创建二维数组储存数据
int** data = (int**)malloc(sizeof(int*) * n);
for (int i = 0; i < n; i++) {
data[i] = (int*)malloc(sizeof(int) * n);
}
//初始化二维数组为0
for (int i = 0; i < n; i++) {
for (int j = 0; j <= i; j++) {
data[i][j] = 0;
}
}
//输入数据
for (int i = 0; i < n; i++) {
for (int j = 0; j <= i; j++) {
scanf("%d", &data[i][j]);
}
}
//结果
int result= fun(n, 0, 0, data);
printf("最大路径是%d\n", result);
}
结果如下:
前面讲到去通过递归的方式来实现这个算法,很明显其时间复杂度为O(2^n),但是如果递归的深度过深的话,也就是说输入的数据很多的话就很容易出现系统计算量过大卡死。对此我们可以通过优化递归的代码来减少时间复杂度,我们可以去创建一个记忆数组来储存前面所递归的结果。举个例子,对于斐波那契数列1 1 2 3 5……,我们可以用递归算法去实现,同样的如果要往很后面算的话也会面临这个问题,如果我们创建这么一个数组array来储存前两个数据的话,到时候我们直接拿出来用就行了比如当前array储存了2和3,那么我要算5的时候就拿出来相加就行了,不需要重新去递归计数2和3了,这时候时间复杂度变为O(n^2)
既然有了这么一个记忆数组,那么我们还可以去通过这个记忆数组来输出这个路径,代码如下:
#include
#include
//比较大小
int max(int a, int b) {
return a > b ? a : b;
}
//递归函数,二维数组op是记忆数组,初始化为0,表示没有访问过
int fun(int n, int i, int j, int** a, int** op) {
if (i == n) {
return 0;
}
//如果记忆数组储存了前面的数据,直接返回就行了
if (op[i][j] != 0)
return op[i][j];
op[i][j] = a[i][j] + max(fun(n, i + 1, j, a, op), fun(n, i + 1, j + 1, a, op));
return op[i][j];
}
//打印结果
void print(int result,int**op,int n) {
puts("");//换行
//输出记忆数组op
printf("记忆数组op结果如下:\n");
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf("%d ", op[i][j]);
}
puts("");
}
printf("最大路径是:%d\n", result);
}
//输出路径
void Find_path(int** op, int** a, int n) {
int j = 0;
printf("路径如下:\n");
printf("%d", a[0][0]);
for (int i = 1; i < n; i++) {
int node = op[i - 1][j] - a[i - 1][j];//减去加上这个位置数字,得到的结果与其左右节对比是否相等
if (node == op[i][j + 1])
j++;
printf("-->%d", a[i][j]);
}
}
int main()
{
int n;
printf("enter your num:");
scanf("%d", &n);
//创建二维数组储存数据
int** data = (int**)malloc(sizeof(int*) * n);
for (int i = 0; i < n; i++) {
data[i] = (int*)malloc(sizeof(int) * n);
}
//初始化二维数组为0
for (int i = 0; i < n; i++) {
for (int j = 0; j <= i; j++) {
data[i][j] = 0;
}
}
//输入数据
for (int i = 0; i < n; i++) {
for (int j = 0; j <=i ; j++) {
scanf("%d", &data[i][j]);
}
}
//op记忆数组
int** op = (int**)malloc(sizeof(int*) * n);
for (int i = 0; i < n; i++) {
op[i] = (int*)malloc(sizeof(int) * n);
}
for (int x = 0; x < n; x++) {
for (int y = 0; y < n; y++)
op[x][y] = 0;//初始化为0,表示未访问
}
int result = fun(n, 0, 0, data,op);
print(result,op,n);
Find_path(op, data, n);
}
#include
#include
#include
int max(int a, int b) {
return a > b ? a : b;
}
//非递归算法函数
void find(int n, int** a, int** op) {
for (int j = 0, i = n - 1; j < n; j++) {
op[i][j] = a[i][j];//先把最后一次数据放入到记忆数组op中
}
for (int x = n - 2; x >= 0; x--) {
for (int y = 0; y <= x; y++) {
int temp = max(op[x + 1][y], op[x + 1][y + 1]);
op[x][y] = temp + a[x][y];
}
}
}
//获取路径储存到path数组当中
void find_path(int n, int* path, int** op, int** a) {
path[0] = a[0][0];
int j = 0;
for (int i = 1; i < n; i++)
{
int node = op[i - 1][j] - a[i - 1][j];
if (node == op[i][j + 1])
j++;
path[i] = a[i][j];
}
}
//输出结果
void print(int* path, int n, int** op) {
printf("记忆数组op结果如下:\n");
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
printf("%d ", op[i][j]);
printf("\n");
}
printf("路径如下:\n");
for (int i = 0; i < n; i++)
printf("%d-->", path[i]);
printf("end\n");
printf("最大路径是:%d\n", op[0][0]);
}
int main()
{
int n;
printf("enter your num:");
scanf("%d", &n);
//创建二维数组储存数据
int** data = (int**)malloc(sizeof(int*) * n);
for (int i = 0; i < n; i++) {
data[i] = (int*)malloc(sizeof(int) * n);
}
//初始化二维数组为0
for (int i = 0; i < n; i++) {
for (int j = 0; j <= i; j++) {
data[i][j] = 0;
}
}
//输入数据
for (int i = 0; i < n; i++) {
for (int j = 0; j <=i ; j++) {
scanf("%d", &data[i][j]);
}
}
//op
int** op = (int**)malloc(sizeof(int*) * n);
for (int i = 0; i < n; i++) {
op[i] = (int*)malloc(sizeof(int) * n);
}
for (int x = 0; x < n; x++) {
for (int y = 0; y < n; y++)
op[x][y] = 0;
}
//储存路径数组path
int* path = (int*)malloc(sizeof(int) * n);
memset(path, 0, sizeof(path));//初始化
find(n, data, op);
find_path(n, path, op, data);
print(path,n,op);
}
结果如下:
以上就是本期的全部内容了,我们下一次见!
分享一张壁纸: