给出一个三角形,找出从顶部至底部的最小路径和。每一步你只能移动到下一行的邻接数字。

例如,给出如下三角形:

[

     [2],

    [3,4],

   [6,5,7],

  [4,1,8,3]

]

从顶部至底部的最小路径和为11(即2+3+5+1=11)。

注意:

加分项-如果你能只使用O(n)的额外空间,n为三角形中的总行数。

 

初始思路

最直接的思路就是把路径都走一遍。即从顶点出发,分别往左中右移动(如果可能的话);然后对走到的位置继续进行同样移动,直到走到最后一行。这样就可以得到一个递归的方案,而递归的结束条件就是前面所说的走到最后一行。伪代码如下:

[最短路径长度] 查找路径(当前节点坐标,当前路径值)

如果是最后一行,返回当前路径值+当前节点值

否则

  如果可以往左下走,左路径 = 当前路径值 + 查找路径(左下节点坐标,当前路径值)

  如果可以往下走,下路径 = 当前路径值 + 查找路径(下节点坐标,当前路径值)

  如果可以往右下走,右路径 = 当前路径值 + 查找路径(右下节点坐标,当前路径值)

  找出左路径,下路径和右路径中的最小值,返回该最小值

结合范例数据仔细分析一下上面的伪代码, 可以发现其中有不少重复的步骤。如2->3->5和2->4->5后面的处理是完全相同的。回想一下我们在 [LeetCode 132] - 回文分割II(Palindrome Partitioning II) 中的做法,可以使用一个map保存已计算过的路径来应对这种重复。这里我们使用std::map<std::pair<int, int>, int>,将某点的坐标作为map的key,从key出发的最小路径作为值。

按以上思路完成代码提交后发现有些测试用例不能通过,如:

[

      [-1]

     [3,2]

   [-3,1,-1]

]

按以上算法得出的值为-2,而期望的值为-1。-2为-1 -> 2-> -3这条路径得出的值,而-1为路径-1 -> 3 -> -3。看来题目中的邻接(英文原文adjacent)规定只能往下或者右走。修改也很简单,将代码中处理向左下走的那部分逻辑去掉即可。最终通过了Judge Small和Judge Large的代码如下:

 1 class Solution {
 2     public:
 3         int minimumTotal(std::vector<std::vector<int> > &triangle)
 4         {
 5             pathInfo.clear();
 6             
 7             if(triangle.empty())
 8             {
 9                 return 0;
10             }
11 
12             return FindMinPath(triangle, 0, 0, 0);
13         }
14         
15     private:
16         int FindMinPath(std::vector<std::vector<int>>& input, int X, int Y, int currentPathValue)
17         {
18             if(X == input.size() - 1)
19             {
20                 return currentPathValue + input[X][Y];
21             }
22             
23             
24             auto iter = pathInfo.find(Coordinate(X, Y));
25             
26             if(iter != pathInfo.end())
27             {
28                 return currentPathValue + iter->second;
29             }
30             
31             
32             //int left = currentPathValue;
33             int down = currentPathValue;
34             int right = currentPathValue;
35             int min = 0;
36             bool minUpdated = false;
37             
38             /*
39             if(Y - 1 >= 0)
40             {
41                 left += FindMinPath(input, X + 1, Y - 1, input[X][Y]);
42                 min = left;
43                 minUpdated = true;
44             }
45             */
46             
47             if(Y < input[X + 1].size())
48             {
49                 down += FindMinPath(input, X + 1, Y, input[X][Y]);
50                 
51                 if(!minUpdated || min > down)
52                 {
53                     min = down;
54                     minUpdated = true;
55                 }
56                 
57                 if(Y + 1 < input[X + 1].size())
58                 {
59                     right += FindMinPath(input, X + 1, Y + 1, input[X][Y]);
60                     if(!minUpdated || min > right)
61                     {
62                         min = right;
63                     }
64                 }
65             }
66             
67                         pathInfo[Coordinate(X, Y)] = min - currentPathValue;
68             
69             return min;
70         }
71 
72         
73         std::map<std::pair<int, int>, int> pathInfo;
74         
75         typedef std::pair<int, int> Coordinate;
76     };
minimumTotal

相关文章: