数塔问题-简单的动态规划
本文最后更新于:2024年8月27日 上午
如下图是一个数塔,从顶部出发在每一个节点可以选择向左或者向右走,一直走到底层,要求找出一条路径,使得路径上的数字之和最大。
1 |
|
算法分析
我们可以这样想,从最后一层倒过来看,到倒数第二层,可以选择一个较大的路径,例如,假设我们一步走到了2这里,下一步应该怎么走?只有19或7这两种选择,既然我们想让总的路径之和最大,那我们肯定每一步都要选大的。我们人脑编译器是很简单的,每次只需要倒着推,到最后一个数据就是我们的最大路径。
数据结构
假设这个数塔的层数是N,我们可以将这个数塔放在一个NxN的data数组里,也许只需要下三角矩阵i>=j。另外,我们还就可以将每一步最大的路径的数据保存在dp数组里。用两重循环来遍历数组,我们要倒着推,所有要i–,二维的j是从左往右,j++。
data | ||||
---|---|---|---|---|
9 | ||||
12 | 15 | |||
10 | 6 | 8 | ||
2 | 18 | 9 | 5 | |
19 | 7 | 10 | 4 | 16 |
dp | ||||
---|---|---|---|---|
59 | ||||
50 | 49 | |||
38 | 34 | 29 | ||
21 | 28 | 19 | 21 | |
19 | 7 | 10 | 4 | 16 |
代码
1 |
|
输出
1 |
|
优化
输出路径
题目可能会要求我们输出我们是怎么走的,在两个表都填写完整后,第一步不用说,肯定的是data[0][0],之后,我们用dp[i][j](还是从dp[0][0]开始)数据减去data数组的这一个位置的数据,我们可以倒着想,我们是用下面两个数据的较大的一个加上data[i][j]数据得到这个dp[i][j]。相减的结果就是较大的那个dp[i+1][j]或者是dp[i+1][j+1]。我们就可以确定是选择了这个路径data[i+1][j]或data[i+1][j+1]。因为这一次我们是正着走的,一条路走到底,每次都选dp大的那一个data数据,只需要循环N-1次就可以了(第一步已确定)。
1 |
|
输出
1 |
|
空间优化
其实dp数组里的数据不需要每一层都储存起来,用过之后就没用了,我们可以用覆盖的方法将二维数组优化为一维数组,也就是滚动数组。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!