经典算法-----数字三角形路径最大问题

 目录

前言

问题描述

解决思路

代码实现(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

解决思路

对于这一类问题我们很容易想到去通过递归的方式来解决,先创建一个二维数组来储存这些数据, 然后去通过递归比较大小,取其中比较大的进入到下一层递归,也就是当前节点加上其左边和右边节点较大者。

代码实现(C语言)

1.递归算法 

#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);
}

结果如下: 

经典算法-----数字三角形路径最大问题_第1张图片

2.递归优化(输出路径)

前面讲到去通过递归的方式来实现这个算法,很明显其时间复杂度为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);
}

结果如下:经典算法-----数字三角形路径最大问题_第2张图片

3.非递归算法(输出路径)

#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);
}

结果如下:

经典算法-----数字三角形路径最大问题_第3张图片

以上就是本期的全部内容了,我们下一次见!

分享一张壁纸:

你可能感兴趣的:(数据结构与算法,算法,c语言,数据结构,递归,最大路径)