liuxuhelloworld's notebook

题目链接

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

解答过程

从动态规划的角度去考虑,并不难想到如何解决这个问题。维护一个二维数组,dp[i][j]表示从top节点到第i行第j列的节点的最小路径sum,而dp[i][j] = min(dp[i-1][j-1], dp[i-1][j]) + triangle[i][j],这样从二维数组的最后一行中找到最小值就是从top节点到最后一行的最小路径sum. 题目中进一步提到是不是可以只使用O(n)的额外空间,其实想一下,dp[i]这一行的计算只依赖dp[i-1]这一行,所以是可以只维护一个一维数组,这个数组存储的是从top节点到当前遍历到的那一行对应的各个元素的最小路径sum. 进一步的,遍历下一行时如何更新这个一维数组呢?dp[i][j] = min(dp[i-1][j-1], dp[i-1][j]) + triangle[i][j],所以只能从右到左进行更新,从左到右更新会覆盖掉还需要进一步使用的原数据。

	public int minimumTotal(List<List<Integer>> triangle) {
		int rows = triangle.size();

		int[] dp = new int[rows + 1];
		for (int i = 0; i <= rows; i++) {
			dp[i] = Integer.MAX_VALUE;
		}

		List<Integer> first = triangle.get(0);
		dp[1] = first.get(0);

		for (int i = 1; i < rows; i++) {
			List<Integer> cur = triangle.get(i);

			for (int j = i + 1; j >= 1; j--) {
				dp[j] = Math.min(dp[j], dp[j-1]) + cur.get(j-1);
			}
		}

		int min = dp[1];
		for (int i = 1; i <= rows; i++) {
			if (dp[i] < min) {
				min = dp[i];
			}
		}

		return min;
	}

注意dp数组的初始化逻辑和triangle第一行的处理。