算法第三章实践报告

1.实践题目:数字三角形 算法

 

2.问题描述:数组

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

 

3.算法描述:设计

  首先,将这个数字三角形存储在一个二维数组num[n+1][n+1]中,且采用左下角的直角三角形的方式存储(第0行和第0列储存为0,方便操做)。例如,将PTA上的样例输入存储为以下所示:递归

  0  0  0  0  0  0for循环

  0  7  0  0  0  0
  0  3  8  0  0  0
  0  8  1  0  0  0
  0  2  7  4  4  0
  0  4  5  2  6  5二叉树

  而后,第1行第1列(7)开始从上到下遍历,并将它置为它上方的数及左上方的数的较大值与它自身的和:num[i][j] = num[i][j] + max(num[i-1][j-1], num[i-1][j]);循环

  遍历完成后,最后一行的数都是它上面的数的较大值的总和,以PTA的样例输入为例,通过上述操做之后该数组变成:遍历

  0  0   0   0   0   0方法

  0  7   0   0   0   0 
  0 10 15  0   0   0 
  0 18 16 15  0   0 
  0 20 25 20 19  0 
  0 24 30 27 26 24

  所以所求的最大路径就是最后一行的最大值。这里使用简单求数组最大值的方法找到了最大值为30:

  int max = 0;
  for (int i = 1; i <= n; i++)
    if (num[n][i] > max)
      max = num[n][i];

3.算法时间及空间复杂度分析:

  时间复杂度:该算法在遍历阶段采用了双层for循环进行遍历,所以时间复杂度为O(n^2)。

  空间复杂度:该算法是直接在原数组上操做的,所以辅助空间较少,空间复杂度为O(1)。

 

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

  这个题目的主要难点在于如何保存数组以及写出递推公式。由这个数字三角形的形状我第一反应是用二叉树来保存,而后使用中序遍历或前序遍从来找到最大路径。但好像没有预设的二叉树的数据结构,并且操做也有诸多困难,所以我最后选择了二维数组。这里我用行列长度比原长度大1的方式,空出第0行和第0列,主要是为了递归时的方便,不用考虑边界的问题。好在这道题的递推公式也不难写,所以我按本身对动态规划的印象写出了num[i][j] = num[i][j] + max(num[i-1][j-1], num[i-1][j])。这道题有一个坑是咱们每每第一反应是“每次分叉都选最大值,那么结果不就是最大路径了吗?”但这实际上是犯了一个常见的错误:认为局部最优解就是总体最优解。例如,样例输入中,咱们每次分叉选择较大值,即7+8+1+7+5=28。但实际上最优解是3+7+8+7+5=30。所以,咱们在解决相似问题的时候,必定要注意这个细节,即局部最优解并不必定等于总体最优解。

相关文章
相关标签/搜索