From 02aa8806ee1f8f3d9cd8b5e863f92b74eac3cee3 Mon Sep 17 00:00:00 2001 From: CyC2018 Date: Sat, 31 Oct 2026 14:03:47 +0800 Subject: [PATCH] =?UTF-8?q?Update=20Leetcode=20=E9=A2=98=E8=A7=A3=20-=20?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E8=A7=84=E5=88=92.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增乘积最大子数组(152);题目链接统一为 leetcode.cn。 --- notes/Leetcode 题解 - 动态规划.md | 97 ++++++++++++++++++++++--------- 1 file changed, 69 insertions(+), 28 deletions(-) diff --git a/notes/Leetcode 题解 - 动态规划.md b/notes/Leetcode 题解 - 动态规划.md index a48f15a1..094d1759 100644 --- a/notes/Leetcode 题解 - 动态规划.md +++ b/notes/Leetcode 题解 - 动态规划.md @@ -15,6 +15,7 @@ * [1. 数组区间和](#1-数组区间和) * [2. 数组中等差递增子区间的个数](#2-数组中等差递增子区间的个数) * [3. 最长有效括号](#3-最长有效括号) + * [4. 乘积最大子数组](#4-乘积最大子数组) * [分割整数](#分割整数) * [1. 分割整数的最大乘积](#1-分割整数的最大乘积) * [2. 按平方数来分割整数](#2-按平方数来分割整数) @@ -55,7 +56,7 @@ 70\. Climbing Stairs (Easy) -[Leetcode](https://leetcode.com/problems/climbing-stairs/description/) / [力扣](https://leetcode-cn.com/problems/climbing-stairs/description/) +[Leetcode](https://leetcode.com/problems/climbing-stairs/description/) / [力扣](https://leetcode.cn/problems/climbing-stairs/description/) 题目描述:有 N 阶楼梯,每次可以上一阶或者两阶,求有多少种上楼梯的方法。 @@ -86,7 +87,7 @@ public int climbStairs(int n) { 198\. House Robber (Medium) -[Leetcode](https://leetcode.com/problems/house-robber/description/) / [力扣](https://leetcode-cn.com/problems/house-robber/description/) +[Leetcode](https://leetcode.com/problems/house-robber/description/) / [力扣](https://leetcode.cn/problems/house-robber/description/) 题目描述:抢劫一排住户,但是不能抢邻近的住户,求最大抢劫量。 @@ -112,7 +113,7 @@ public int rob(int[] nums) { 213\. House Robber II (Medium) -[Leetcode](https://leetcode.com/problems/house-robber-ii/description/) / [力扣](https://leetcode-cn.com/problems/house-robber-ii/description/) +[Leetcode](https://leetcode.com/problems/house-robber-ii/description/) / [力扣](https://leetcode.cn/problems/house-robber-ii/description/) 题目描述:住户围成一圈,首尾两户相邻。 @@ -170,7 +171,7 @@ dp[i] 表示 i 封信都装错的方式数量。第 i 封信装进了第 j 个 64\. Minimum Path Sum (Medium) -[Leetcode](https://leetcode.com/problems/minimum-path-sum/description/) / [力扣](https://leetcode-cn.com/problems/minimum-path-sum/description/) +[Leetcode](https://leetcode.com/problems/minimum-path-sum/description/) / [力扣](https://leetcode.cn/problems/minimum-path-sum/description/) ```text [[1,3,1], @@ -210,7 +211,7 @@ public int minPathSum(int[][] grid) { 62\. Unique Paths (Medium) -[Leetcode](https://leetcode.com/problems/unique-paths/description/) / [力扣](https://leetcode-cn.com/problems/unique-paths/description/) +[Leetcode](https://leetcode.com/problems/unique-paths/description/) / [力扣](https://leetcode.cn/problems/unique-paths/description/) 题目描述:统计从矩阵左上角到右下角的路径总数,每次只能向右或者向下移动。 @@ -283,7 +284,7 @@ public int maximalSquare(char[][] matrix) { 303\. Range Sum Query - Immutable (Easy) -[Leetcode](https://leetcode.com/problems/range-sum-query-immutable/description/) / [力扣](https://leetcode-cn.com/problems/range-sum-query-immutable/description/) +[Leetcode](https://leetcode.com/problems/range-sum-query-immutable/description/) / [力扣](https://leetcode.cn/problems/range-sum-query-immutable/description/) ```text Given nums = [-2, 0, 3, -5, 2, -1] @@ -317,7 +318,7 @@ class NumArray { 413\. Arithmetic Slices (Medium) -[Leetcode](https://leetcode.com/problems/arithmetic-slices/description/) / [力扣](https://leetcode-cn.com/problems/arithmetic-slices/description/) +[Leetcode](https://leetcode.com/problems/arithmetic-slices/description/) / [力扣](https://leetcode.cn/problems/arithmetic-slices/description/) ```text A = [0, 1, 2, 3, 4] @@ -441,13 +442,53 @@ public int longestValidParentheses(String s) { } ``` +### 4. 乘积最大子数组 + +152\. Maximum Product Subarray (Medium) + +[Leetcode](https://leetcode.com/problems/maximum-product-subarray/) / [力扣](https://leetcode.cn/problems/maximum-product-subarray/) + +```text +Input: [3, -1, 2, -4] +Output: 24,子数组为整个数组 +``` + +与 [子数组最大的和](Leetcode%20题解%20-%20贪心思想.md#10-子数组最大的和) 类似,都看以当前元素结尾的子数组,但乘积不能只保存最大值:负数乘上最小的负积会变成最大的正积。所以同时维护以 nums[i] 结尾的最大积 max 和最小积 min,三个候选是 nums[i] 本身、max × nums[i] 和 min × nums[i]。 + +以 [3, -1, 2, -4] 为例: + +```text +i nums[i] max min 结果 +0 3 3 3 3 +1 -1 -1 -3 3 +2 2 2 -6 3 +3 -4 24 -8 24 +``` + +走到 2 时最大积只有 2,-6 看起来没用,但它乘上 -4 就得到 24。只保存最大积的话,最后只能得到 3。 + +```java +public int maxProduct(int[] nums) { + int max = nums[0], min = nums[0], ret = nums[0]; + for (int i = 1; i < nums.length; i++) { + int a = max * nums[i], b = min * nums[i]; + max = Math.max(nums[i], Math.max(a, b)); + min = Math.min(nums[i], Math.min(a, b)); + ret = Math.max(ret, max); + } + return ret; +} +``` + +只遍历一遍数组,时间复杂度 O(N);只保存三个变量,空间复杂度 O(1)。 + ## 分割整数 ### 1. 分割整数的最大乘积 343\. Integer Break (Medium) -[Leetcode](https://leetcode.com/problems/integer-break/description/) / [力扣](https://leetcode-cn.com/problems/integer-break/description/) +[Leetcode](https://leetcode.com/problems/integer-break/description/) / [力扣](https://leetcode.cn/problems/integer-break/description/) 题目描述:把正整数 n 拆成至少两个正整数的和,求这些整数乘积的最大值。For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 + 3 + 4). @@ -470,7 +511,7 @@ public int integerBreak(int n) { 279\. Perfect Squares (Medium) -[Leetcode](https://leetcode.com/problems/perfect-squares/description/) / [力扣](https://leetcode-cn.com/problems/perfect-squares/description/) +[Leetcode](https://leetcode.com/problems/perfect-squares/description/) / [力扣](https://leetcode.cn/problems/perfect-squares/description/) 题目描述:把 n 表示成若干个完全平方数的和,求最少需要几个。For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9. @@ -510,7 +551,7 @@ private List generateSquareList(int n) { 91\. Decode Ways (Medium) -[Leetcode](https://leetcode.com/problems/decode-ways/description/) / [力扣](https://leetcode-cn.com/problems/decode-ways/description/) +[Leetcode](https://leetcode.com/problems/decode-ways/description/) / [力扣](https://leetcode.cn/problems/decode-ways/description/) 题目描述:字母 A \~ Z 分别编码为 1 \~ 26,求一个数字串有多少种解码方法。Given encoded message "12", it could be decoded as "AB" (1 2) or "L" (12). @@ -560,7 +601,7 @@ public int numDecodings(String s) { 300\. Longest Increasing Subsequence (Medium) -[Leetcode](https://leetcode.com/problems/longest-increasing-subsequence/description/) / [力扣](https://leetcode-cn.com/problems/longest-increasing-subsequence/description/) +[Leetcode](https://leetcode.com/problems/longest-increasing-subsequence/description/) / [力扣](https://leetcode.cn/problems/longest-increasing-subsequence/description/) ```java public int lengthOfLIS(int[] nums) { @@ -629,7 +670,7 @@ private int binarySearch(int[] tails, int len, int key) { 646\. Maximum Length of Pair Chain (Medium) -[Leetcode](https://leetcode.com/problems/maximum-length-of-pair-chain/description/) / [力扣](https://leetcode-cn.com/problems/maximum-length-of-pair-chain/description/) +[Leetcode](https://leetcode.com/problems/maximum-length-of-pair-chain/description/) / [力扣](https://leetcode.cn/problems/maximum-length-of-pair-chain/description/) ```text Input: [[1,2], [2,3], [3,4]] @@ -665,7 +706,7 @@ public int findLongestChain(int[][] pairs) { 376\. Wiggle Subsequence (Medium) -[Leetcode](https://leetcode.com/problems/wiggle-subsequence/description/) / [力扣](https://leetcode-cn.com/problems/wiggle-subsequence/description/) +[Leetcode](https://leetcode.com/problems/wiggle-subsequence/description/) / [力扣](https://leetcode.cn/problems/wiggle-subsequence/description/) ```text Input: [1,7,4,9,2,5] @@ -726,7 +767,7 @@ public int wiggleMaxLength(int[] nums) { 1143\. Longest Common Subsequence -[Leetcode](https://leetcode.com/problems/longest-common-subsequence/) / [力扣](https://leetcode-cn.com/problems/longest-common-subsequence/) +[Leetcode](https://leetcode.com/problems/longest-common-subsequence/) / [力扣](https://leetcode.cn/problems/longest-common-subsequence/) ```java public int longestCommonSubsequence(String text1, String text2) { @@ -850,7 +891,7 @@ public int knapsack(int W, int N, int[] weights, int[] values) { 416\. Partition Equal Subset Sum (Medium) -[Leetcode](https://leetcode.com/problems/partition-equal-subset-sum/description/) / [力扣](https://leetcode-cn.com/problems/partition-equal-subset-sum/description/) +[Leetcode](https://leetcode.com/problems/partition-equal-subset-sum/description/) / [力扣](https://leetcode.cn/problems/partition-equal-subset-sum/description/) ```text Input: [1, 5, 11, 5] @@ -892,7 +933,7 @@ private int computeArraySum(int[] nums) { 494\. Target Sum (Medium) -[Leetcode](https://leetcode.com/problems/target-sum/description/) / [力扣](https://leetcode-cn.com/problems/target-sum/description/) +[Leetcode](https://leetcode.com/problems/target-sum/description/) / [力扣](https://leetcode.cn/problems/target-sum/description/) ```text Input: nums is [1, 1, 1, 1, 1], S is 3. @@ -966,7 +1007,7 @@ private int findTargetSumWays(int[] nums, int start, int S) { 474\. Ones and Zeroes (Medium) -[Leetcode](https://leetcode.com/problems/ones-and-zeroes/description/) / [力扣](https://leetcode-cn.com/problems/ones-and-zeroes/description/) +[Leetcode](https://leetcode.com/problems/ones-and-zeroes/description/) / [力扣](https://leetcode.cn/problems/ones-and-zeroes/description/) ```text Input: Array = {"10", "0001", "111001", "1", "0"}, m = 5, n = 3 @@ -1006,7 +1047,7 @@ public int findMaxForm(String[] strs, int m, int n) { 322\. Coin Change (Medium) -[Leetcode](https://leetcode.com/problems/coin-change/description/) / [力扣](https://leetcode-cn.com/problems/coin-change/description/) +[Leetcode](https://leetcode.com/problems/coin-change/description/) / [力扣](https://leetcode.cn/problems/coin-change/description/) ```text Example 1: @@ -1046,7 +1087,7 @@ public int coinChange(int[] coins, int amount) { 518\. Coin Change II (Medium) -[Leetcode](https://leetcode.com/problems/coin-change-ii/description/) / [力扣](https://leetcode-cn.com/problems/coin-change-ii/description/) +[Leetcode](https://leetcode.com/problems/coin-change-ii/description/) / [力扣](https://leetcode.cn/problems/coin-change-ii/description/) ```text Input: amount = 5, coins = [1, 2, 5] @@ -1080,7 +1121,7 @@ public int change(int amount, int[] coins) { 139\. Word Break (Medium) -[Leetcode](https://leetcode.com/problems/word-break/description/) / [力扣](https://leetcode-cn.com/problems/word-break/description/) +[Leetcode](https://leetcode.com/problems/word-break/description/) / [力扣](https://leetcode.cn/problems/word-break/description/) ```text s = "leetcode", @@ -1113,7 +1154,7 @@ public boolean wordBreak(String s, List wordDict) { 377\. Combination Sum IV (Medium) -[Leetcode](https://leetcode.com/problems/combination-sum-iv/description/) / [力扣](https://leetcode-cn.com/problems/combination-sum-iv/description/) +[Leetcode](https://leetcode.com/problems/combination-sum-iv/description/) / [力扣](https://leetcode.cn/problems/combination-sum-iv/description/) ```text nums = [1, 2, 3] @@ -1163,7 +1204,7 @@ public int combinationSum4(int[] nums, int target) { 309\. Best Time to Buy and Sell Stock with Cooldown (Medium) -[Leetcode](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/description/) / [力扣](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/description/) +[Leetcode](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/description/) / [力扣](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-cooldown/description/) 题目描述:可以进行多次交易,但卖出之后需要有一天的冷却时间才能再次买入。 @@ -1197,7 +1238,7 @@ public int maxProfit(int[] prices) { 714\. Best Time to Buy and Sell Stock with Transaction Fee (Medium) -[Leetcode](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/description/) / [力扣](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/description/) +[Leetcode](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/description/) / [力扣](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/description/) ```text Input: prices = [1, 3, 2, 8, 4, 9], fee = 2 @@ -1239,7 +1280,7 @@ public int maxProfit(int[] prices, int fee) { 123\. Best Time to Buy and Sell Stock III (Hard) -[Leetcode](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/description/) / [力扣](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/description/) +[Leetcode](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/description/) / [力扣](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/description/) 四个变量依次是到当天为止完成第一次买入、第一次卖出、第二次买入、第二次卖出后的最大收益,第二次买入以第一次卖出的收益为起点。 @@ -1269,7 +1310,7 @@ public int maxProfit(int[] prices) { 188\. Best Time to Buy and Sell Stock IV (Hard) -[Leetcode](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/description/) / [力扣](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iv/description/) +[Leetcode](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/description/) / [力扣](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iv/description/) maxProfit[i][j] 表示最多交易 i 次、到第 j 天为止的最大收益。第 j 天要么不卖出,收益为 maxProfit[i][j - 1];要么在之前的某天 m 买入、第 j 天卖出,收益为 prices[j] + max(maxProfit[i - 1][m] - prices[m]),localMax 在遍历 j 时维护这个最大值。k >= n / 2 时次数不构成限制,累加所有上涨的差价即可。 @@ -1303,7 +1344,7 @@ public int maxProfit(int k, int[] prices) { 583\. Delete Operation for Two Strings (Medium) -[Leetcode](https://leetcode.com/problems/delete-operation-for-two-strings/description/) / [力扣](https://leetcode-cn.com/problems/delete-operation-for-two-strings/description/) +[Leetcode](https://leetcode.com/problems/delete-operation-for-two-strings/description/) / [力扣](https://leetcode.cn/problems/delete-operation-for-two-strings/description/) ```text Input: "sea", "eat" @@ -1334,7 +1375,7 @@ public int minDistance(String word1, String word2) { 72\. Edit Distance (Medium) -[Leetcode](https://leetcode.com/problems/edit-distance/description/) / [力扣](https://leetcode-cn.com/problems/edit-distance/description/) +[Leetcode](https://leetcode.com/problems/edit-distance/description/) / [力扣](https://leetcode.cn/problems/edit-distance/description/) ```text Example 1: @@ -1395,7 +1436,7 @@ public int minDistance(String word1, String word2) { 650\. 2 Keys Keyboard (Medium) -[Leetcode](https://leetcode.com/problems/2-keys-keyboard/description/) / [力扣](https://leetcode-cn.com/problems/2-keys-keyboard/description/) +[Leetcode](https://leetcode.com/problems/2-keys-keyboard/description/) / [力扣](https://leetcode.cn/problems/2-keys-keyboard/description/) 题目描述:最开始只有一个字符 A,问需要多少次操作能够得到 n 个字符 A,每次操作可以复制当前所有的字符,或者粘贴。