Day10 备忘录
1、931. 下降路径最小和
- 思路:
- 维护二维DP数组,记录每一个格子对应的最小路径。
class Solution { public int minFallingPathSum(int[][] matrix) { int rows = matrix.length; int cols = matrix[0].length; //表示每一层的最小路径和 int[][] dp = new int[rows][cols]; for (int i = 0; i < cols; i++) { dp[0][i] = matrix[0][i]; } for (int i = 1; i < rows; i++) { for (int j = 0; j < cols; j++) { int temp = dp[i - 1][j]; if (j - 1 >= 0){ temp = Math.min(dp[i - 1][j - 1],temp); } if (j + 1 < cols){ temp = Math.min(dp[i - 1][j + 1],temp); } dp[i][j] = temp + matrix[i][j]; } } int ans = dp[rows - 1][0]; for (int i = 1; i < cols; i++) { ans = Math.min(dp[rows - 1][i],ans); } return ans; } } - 数组空间优化
- 只用记录上一层的最小路径就好,可以优化成一个 长的一维数组
class Solution { public int minFallingPathSum(int[][] matrix) { int rows = matrix.length; int cols = matrix[0].length; int ans = Integer.MAX_VALUE; //表示每一层的最小路径和 int[] dp = new int[cols + 1]; for (int i = 0; i < cols; i++) { dp[i] = matrix[0][i]; } //确保 dp[cols] = Integer.MAX_VALUE; for (int i = 1; i < rows; i++) { int temp = 0, last = Integer.MAX_VALUE; for (int j = 0; j < cols; j++) { //保存当前dp[j]供下一次dp[j+1]求dp[j-1] temp = dp[j]; dp[j] = Math.min(Math.min(last, dp[j]), dp[j + 1]) + matrix[i][j]; last = temp; } } for (int item : dp) { ans = Math.min(item, ans); } return ans; } }
2、53. 最大子数组和
- 思路:
- 动态规划。dp数组表示以i为结尾的最大子数组和
- dp数组可以优化为常数
class Solution { public int maxSubArray(int[] nums) { int ans = nums[0]; int max = nums[0]; for (int i = 1; i < nums.length; i++) { max = Math.max(max + nums[i],nums[i]); ans = Math.max(ans,max); } return ans; } } - 分治
class Solution { public int maxSubArray(int[] nums) { return getInfo(nums,0,nums.length - 1); } public int getAns(int[] nums, int l, int mid, int r) { // 一定会包含 nums[mid] 这个元素 int sum = 0; int leftSum = Integer.MIN_VALUE; // 左半边包含 nums[mid] 元素,最多可以到什么地方 // 走到最边界,看看最值是什么 // 计算以 mid 结尾的最大的子数组的和 for (int i = mid; i >= l; i--) { sum += nums[i]; if (sum > leftSum) { leftSum = sum; } } sum = 0; int rightSum = Integer.MIN_VALUE; // 右半边不包含 nums[mid] 元素,最多可以到什么地方 // 计算以 mid+1 开始的最大的子数组的和 for (int i = mid + 1; i <= r; i++) { sum += nums[i]; if (sum > rightSum) { rightSum = sum; } } return leftSum + rightSum; } public int getInfo(int[] nums, int l, int r) { if (l == r) { return nums[l]; } int mid = l + (r - l) / 2; return Math.max( getInfo(nums, l, mid), Math.max(getInfo(nums, mid + 1, r), getAns(nums, l, mid, r))); } }