LeetCode 120.三角形最小路径和——详解

题目描述

在这里插入图片描述

误区分析

有些朋友可能第一反应会想到使用贪心算法(追求当前最优解),移动到下一步两个结点中较小的那个就好了。这个想法看似没什么问题,而且大部分案例都能通过,但是遇上类似这样的案例就过不了了:

[[-1],[2,3],[1,-1,-3]]
-1
 2	 3
 1	-1 	-3

这个案例用贪心算法的思想,结果应该为0(-1 + 2 + -1 = 0)
但是正确答案却是-1(-1 + 3 + -3 = -1)
由此可见用贪心算法做这道题是不可行

正确思路分析

  • 这道题可以采用类似思路的动态规划,记录子问题的全局最优解,用空间换时间得到正确答案。
  • 我们新建一个二维数组(相当于复制了一个一样的空三角形),在对应的位置上同步记录到达原三角形上该结点的最小路径和,最后只需要取出最后一行中最小的值即可。

图解:

在这里插入图片描述

  • 左边三角形里,黄色的数值其实是dp数组里对应位置的值。解释一下左图的意思就是:从第二行开始,每个数字都要找指向他的那两个(两边的位置上只有一个)位置所对应的dp值(就是黄色数字)中,较小的那个值和自身相加然后把结果储存到自身所对应的dp数组的位置上(就是变成黄色数字)
  • 右边其实就是dp数组
  • 然后呢最后只要在dp数组最下面那行,找到最小值就可以了

代码展示

int minimumTotal(int** triangle, int triangleSize, int* triangleColSize) {
	int a = triangleColSize[triangleSize - 1];
	int dp[200][200] = { 0 };
	int i = 0, j = 0;
	int min = 0;
	for (i = 0; i < triangleSize; i++) {
		for (j = 0; j < triangleColSize[i]; j++) {
			if (j == 0) {
				if (i == 0) {
					dp[i][j] = triangle[i][j];
					printf("dp[%d][%d] = %d\n", i, j, dp[i][j]);
				}
				else {
					dp[i][j] = dp[i - 1][j] + triangle[i][j];
					printf("dp[%d][%d] = %d\n", i, j, dp[i][j]);
				}
			}
			else if (j == triangleColSize[i] - 1) {
				dp[i][j] = dp[i - 1][j - 1] + triangle[i][j];
				printf("dp[%d][%d] = %d\n", i, j, dp[i][j]);
			}
			else {
				if (dp[i - 1][j - 1] < dp[i - 1][j]) {
					dp[i][j] = dp[i - 1][j - 1] + triangle[i][j];
				}
				else {
					dp[i][j] = dp[i - 1][j] + triangle[i][j];
				}
				printf("dp[%d][%d] = %d\n", i, j, dp[i][j]);
			}
		}
	}
	min = dp[triangleSize - 1][0];
	printf("min = %d\n", min);
	printf("triangleColSize[triangleSize - 1] = %d", triangleColSize[triangleSize - 1]);
	for (j = 0; j < triangleColSize[triangleSize - 1]; j++) {
		if (dp[triangleSize - 1][j] < min) {
			min = dp[triangleSize - 1][j];
		}
	}
	return min;
}

要特别注意dp数组和原数组的关系哦!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值