According to above, (2,1) (3,1) (3,2) are repeated. If do regular DFS, every node has 2 choices, left or right in the next row. Therefore, time complexity is O(2n) . So another method is to store all the minimal path from any node to the last row. We let dfs(int x, int y) records the minimal path sum from (x,y) to the last row.
Space complexity is O(n2) (sumPath[][]). Because every node is only needed to compute once, there are (n(n+1))/2 times of computation, if every computation is O(1) , then time complexity is O(n2)
If we do from bottom to up to record the minimal path for each node, we only need a int[] minPath to store the minimal path for each node of next row. Then taking advantage of minPath[] infers the minimal path of each node in current row. The result is minPath[0][0]. The space complexity is O(n) , the time complexity is O(n2)
Deciding which part of the cache to discard to save space can be a hard job.
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
miniPath = [[0] * len(triangle[-1])] * len(triangle)
for i in range(len(triangle[-1])):
miniPath[-1][i] = triangle[-1][i]
for i in reversed(range(len(triangle)-1)):
for j in range(len(triangle[i])):
miniPath[i][j] = min(miniPath[i+1][j], miniPath[i+1][j+1]) + triangle[i][j]
print(miniPath)
return miniPath[0][0]
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
# edge case
if len(triangle) == 0:
return 0
elif len(triangle) == 1:
return triangle[0][0]
l = len(triangle)
sumPath = [[-1]*l for i in range(l)]
return self.dfs(triangle, 0, 0, sumPath)
def dfs(self, triangle, x, y, sumPath):
# stop condition
if x == len(triangle):
return 0
# regular case
if sumPath[x][y] == -1:
left = self.dfs(triangle,x+1,y, sumPath)
right = self.dfs(triangle,x+1,y+1, sumPath)
sumPath[x][y] = triangle[x][y] + min(left, right)
return sumPath[x][y]
Python example 2: space complex = O(n)
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
for(int i = triangle.size() - 2; i >= 0; i --)
for(int j = triangle.get(i).size() - 1; j >= 0; j --) {
int value = triangle.get(i).get(j) + Math.min(triangle.get(i+1).get(j), triangle.get(i+1).get(j+1));
triangle.get(i).set(j, value);
}
return triangle.get(0).get(0);
}
}
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
miniPath = []
for i in range(len(triangle[-1])):
miniPath.append(triangle[-1][i])
for i in reversed(range(len(triangle)-1)):
for j in range(0, i+1):
miniPath[j] = min(miniPath[j], miniPath[j+1]) + triangle[i][j]
return miniPath[0]