[LeetCode] 120. triangular minimum path and

Topic link: https: //leetcode-cn.com/problems/triangle/

Subject description:

Given a triangle, find the minimum and the top-down path. Each step can move to the next line adjacent nodes.

For example, given triangle:

[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]

Top-down and minimum path 11 (i.e., 2 + 3 + 5 + 1 = 11).

Description:

If you can use only O (n) extra space (n number of rows as a triangle) to solve this problem, then your algorithm will be a plus.

Ideas:

My first idea is to use the DFS, top to bottom traversal of all paths, as shown below:

def minimumTotal(self, triangle: List[List[int]]) -> int:
        self.res = float("inf")
        row = len(triangle)
        def helper(level, i, j, tmp):
            if level == row:
                self.res = min(self.res, tmp)
                return 
            if 0 <= i < len(triangle[level]):
                helper(level + 1, i, i+1, tmp + triangle[level][i])
            if 0 <= j < len(triangle[level]):
                helper(level + 1, j, j+1, tmp + triangle[level][j])
        # 层level, 访问下一层两个节点位置i,j , 目前总和tmp
        helper(0, -1, 0, 0)
        return self.res

The above approach through all the paths, so time out, so we use DFS with memory (top-down dynamic programming),

  def minimumTotal(self, triangle) -> int:
        import functools
        row = len(triangle)

        @functools.lru_cache(None)
        def helper(level, i, j):
            if level == row:
                return 0
            res = 0
            a = float("inf")
            b = float("inf")
            if 0 <= i < len(triangle[level]):
                a = helper(level + 1, i, i + 1) + triangle[level][i]
            if 0 <= j < len(triangle[level]):
                b = helper(level + 1, j, j + 1) + triangle[level][j]
            res += min(a, b)
            return res

        return helper(0, -1, 0) 

Next, we use a bottom-up dynamic programming

We first use \ (O (n ^ 2) \) space, it is easier to understand

dp[i][j]To go from top to bottom represents i,jthe value of the position of the minimum path.

Dynamic equation: dp[i][j] = min(dp[i-1][j], dp[i-1][j+1]) + triangle[i][j]

Of course, to be considered separately for the first and last.

def minimumTotal(self, triangle: List[List[int]]) -> int:
        n = len(triangle)
        if n == 0:
            return 0
        # 建dp空间
        dp = [[0] * i for i in range(n)]
        dp[0][0] = triangle[0][0]

        for i in range(1, n):
            for k in range(i + 1):
                if k == 0:
                    dp[i][k] = dp[i - 1][k] + triangle[i][k]
                elif k == i:
                    dp[i][k] = dp[i - 1][k - 1] + triangle[i][k]
                else:
                    dp[i][k] = min(dp[i - 1][k - 1], dp[i - 1][k]) + triangle[i][k]
        return min(dp[-1])

In fact, we only use dp every time a layer of data, if we backwards, upwards from the bottom can be optimized to \ (O (n) \) space

def minimumTotal(self, triangle: List[List[int]]) -> int:
        row = len(triangle)
        dp = [0] * row
        for i in range(len(triangle[-1])):
            dp[i] = triangle[-1][i]
        #print(dp)
        for i in range(row - 2, -1, -1):
            for j in range(i + 1):
                dp[j] = min(dp[j], dp[j + 1]) + triangle[i][j]
        return dp[0]          

java

class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        int row = triangle.size();
        int[] dp = new int[row];
        for (int i = 0; i < row; i++) dp[i] = triangle.get(row - 1).get(i);
        for (int i = row - 2; i >= 0; i--)
            for (int j = 0; j <= i; j++)
                dp[j] = Math.min(dp[j], dp[j + 1]) + triangle.get(i).get(j);
        return dp[0];
    }
}

Guess you like

Origin www.cnblogs.com/powercai/p/11129024.html