java 数字三角形

来源:互联网 发布:js 运动轨迹 编辑:程序博客网 时间:2024/05/22 02:21

1. 实践题目

7-1 数字三角形


2. 问题描述

给定一个由 n行数字组成的数字三角形如下图所示。试设计一个算法,计算出从三角形 的顶至底的一条路径(每一步可沿左斜线向下或右斜线向下),使该路径经过的数字总和最大。


3. 算法描述(不能粘贴程序)

 



用一个二维数组来储存数据,从底向上的进行叠加,从b[i][j]出发,下一步只能是 b[i-1][j]或者b[i-1][j+1],每算一个maxSum(r,j)就保存起来,下次用到时就直接取用,避免了重复计算的问题。成为记忆递归型的动态规划。

递归公式:


原问题的最优值是 b[1][1]

终止条件是 b[1][1]

 

4. 算法时间及空间复杂度分析(要有分析过程)

时间复杂度为O(n2),因为三角形的数字总和为n(n+1)/2,需要两次循环。

空间复杂度S(n*n),因为需要一个二维数组来存放数据

 

5. 程序运行截图

 

6.心得体会(对本次实践收获及疑惑进行总结)

动态规划就是聪明的穷举法,以及聪明的分治法。都是把原问题分成若干子问题。

若子问题都不会重复,就使用分治法解决。若出现重叠子问题,就用动态规划。如果用分治法,将会浪费大量时间进行重复求解子问题,不停的采用递归方法,程序就会超时。

 

那么从时间上优化,就可以想到如果每算出一个MaxSum(r,j)就保存起来,下次用到其值的时候直接取用,则可免去重复计算。使之成为记忆递归型的动态规划。

 

如果从空间上优化,一开始我采用的是二维数组存取数据的方法,最优条件为b[1][1],(此时空间复杂度为S(n*n))。

maxSum[i][j] = max(maxSum[i+1][j],maxSum[i+1][j+1]) + D[i][j];    

cout << maxSum[1][1] << endl;

后来觉得二维数组浪费存储空间,就用一个一维数组来储存。从底层一行行向上递推,即只要存储一行的MaxSum值就可以。(此时空间复杂度为S(n))。

maxSum[j] = max(maxSum[j],maxSum[j+1]) + D[i][j];    

cout << maxSum[1] << endl;

通过以上两个优化调试,充分体现了原问题的最优解包含了子问题的最优解。


源代码地址:https://github.com/TFknight/PythonStudy/blob/master/algorithm/numbersj.java