diff --git a/docs/notes/Leetcode 题解 - 动态规划.md b/docs/notes/Leetcode 题解 - 动态规划.md index fd51bf13..f3e0c88b 100644 --- a/docs/notes/Leetcode 题解 - 动态规划.md +++ b/docs/notes/Leetcode 题解 - 动态规划.md @@ -904,7 +904,7 @@ Explanation: there are four ways to make up the amount: ```java public int change(int amount, int[] coins) { - if (amount == 0 || coins == null || coins.length == 0) { + if (coins == null) { return 0; } int[] dp = new int[amount + 1]; diff --git a/notes/Leetcode 题解 - 动态规划.md b/notes/Leetcode 题解 - 动态规划.md index 59aa4be7..9ee08d15 100644 --- a/notes/Leetcode 题解 - 动态规划.md +++ b/notes/Leetcode 题解 - 动态规划.md @@ -57,6 +57,7 @@

+ 考虑到 dp[i] 只与 dp[i - 1] 和 dp[i - 2] 有关,因此可以只用两个变量来存储 dp[i - 1] 和 dp[i - 2],使得原来的 O(N) 空间复杂度优化为 O(1) 复杂度。 ```java @@ -87,6 +88,7 @@ public int climbStairs(int n) {

+ ```java public int rob(int[] nums) { int pre2 = 0, pre1 = 0; @@ -140,6 +142,7 @@ private int rob(int[] nums, int first, int last) {

+ ## 5. 母牛生产 [程序员代码面试指南-P181](#) @@ -151,6 +154,7 @@ private int rob(int[] nums, int first, int last) {

+ # 矩阵路径 ## 1. 矩阵的最小路径和 @@ -196,6 +200,7 @@ public int minPathSum(int[][] grid) { 题目描述:统计从矩阵左上角到右下角的路径总数,每次只能向右或者向下移动。

+ ```java public int uniquePaths(int m, int n) { int[] dp = new int[n]; @@ -416,6 +421,7 @@ public int numDecodings(String s) {

+ 对于一个长度为 N 的序列,最长递增子序列并不一定会以 SN 为结尾,因此 dp[N] 不是序列的最长递增子序列的长度,需要遍历 dp 数组找出最大值才是所要的结果,max{ dp[i] | 1 <= i <= N} 即为所求。 ## 1. 最长递增子序列 @@ -582,6 +588,7 @@ public int wiggleMaxLength(int[] nums) {

+ 对于长度为 N 的序列 S1 和长度为 M 的序列 S2,dp[N][M] 就是序列 S1 和序列 S2 的最长公共子序列长度。 与最长递增子序列相比,最长公共子序列有以下不同点: @@ -621,6 +628,7 @@ public int lengthOfLCS(int[] nums1, int[] nums2) {

+ ```java // W 为背包总体积 // N 为物品数量 @@ -649,6 +657,7 @@ public int knapsack(int W, int N, int[] weights, int[] values) {

+ 因为 dp[j-w] 表示 dp[i-1][j-w],因此不能先求 dp[i][j-w],防止将 dp[i-1][j-w] 覆盖。也就是说要先计算 dp[i][j] 再计算 dp[i][j-w],在程序实现时需要按倒序来循环求解。 ```java @@ -860,17 +869,20 @@ return -1. ```java public int coinChange(int[] coins, int amount) { - int[] dp = new int[amount + 1]; - Arrays.fill(dp, amount + 1); - dp[0] = 0; - for (int i = 1; i < dp.length; i++) { - for (int j = 0; j < coins.length; j++) { - if (coins[j] <= i) { - dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1); - } + int[] dp = new int[amount + 1]; + for (int coin : coins) { + for (int i = coin; i <= amount; i++) { //将逆序遍历改为正序遍历 + if (i == coin) { + dp[i] = 1; + } else if (dp[i] == 0 && dp[i - coin] != 0) { + dp[i] = dp[i - coin] + 1; + + } else if (dp[i - coin] != 0) { + dp[i] = Math.min(dp[i], dp[i - coin] + 1); } } - return dp[amount] > amount ? -1 : dp[amount]; + } + return dp[amount] == 0 ? -1 : dp[amount]; } ``` @@ -892,7 +904,7 @@ Explanation: there are four ways to make up the amount: ```java public int change(int amount, int[] coins) { - if (amount == 0 || coins == null || coins.length == 0) { + if (coins == null) { return 0; } int[] dp = new int[amount + 1]; @@ -992,8 +1004,7 @@ public int combinationSum4(int[] nums, int target) { 题目描述:交易之后需要有一天的冷却时间。 -

- +

```java public int maxProfit(int[] prices) { @@ -1035,6 +1046,7 @@ The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8. 题目描述:每交易一次,都要支付一定的费用。

+ ```java public int maxProfit(int[] prices, int fee) { int N = prices.length;