动态规划
新名字的故事
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
123. 买卖股票的最佳时机 III
题目描述:给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。解题思路:动态规划,每天交易结束时可能有两种情况,一是手上有股票二是手上无股票,然后在这个基础上加上交易次数,当前次数的交易次数只和当前和上一次交易次数有关,然后进行关系转移,代码如下:class Solution: def maxProfit(self, prices: List原创 2021-01-09 17:40:07 · 122 阅读 · 0 评论 -
932. 漂亮数组
题目描述:对于某些固定的 N,如果数组 A 是整数 1, 2, …, N 组成的排列,使得:对于每个 i < j,都不存在 k 满足 i < k < j 使得 A[k] * 2 = A[i] + A[j]。那么数组 A 是漂亮数组。给定 N,返回任意漂亮数组 A(保证存在一个)。解题思路:(1)漂亮数组进行放射变换之后还是漂亮数组(2)如果左边的漂亮数组都是奇数,右边的漂亮数组都是偶数,那么左边加上右边也是漂亮数组,因为奇数+偶数一定是奇数方案一:动态规划class Solut原创 2021-01-05 13:00:08 · 271 阅读 · 0 评论 -
605. 种花问题
题目描述:假设你有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花卉不能种植在相邻的地块上,它们会争夺水源,两者都会死去。给定一个花坛(表示为一个数组包含0和1,其中0表示没种植花,1表示种植了花),和一个数 n 。能否在不打破种植规则的情况下种入 n 朵花?能则返回True,不能则返回False。解题思路一:动态规划,首先计算原有花团中的花,然后dp[i][0]表示当前位置i不种花到i位置可种花的最大值,dp[i][1]表示当前位置i种花到位置i为止可以种花的最大数目,代码如下:clas原创 2021-01-01 21:58:23 · 143 阅读 · 0 评论 -
241. 为运算表达式设计优先级
题目描述:给定一个含有数字和运算符的字符串,为表达式添加括号,改变其运算优先级以求出不同的结果。你需要给出所有可能的组合的结果。有效的运算符号包含 +, - 以及 * 。解题思路一:对于每一个运算符号,先执行两边的表达式,然后再处理当前这个符号,采用分治的思想,代码如下:class Solution: def diffWaysToCompute(self, input: str) -> List[int]: # res = set() nums = []原创 2020-12-29 16:27:54 · 153 阅读 · 0 评论 -
714. 买卖股票的最佳时机含手续费
题目描述:给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;非负整数 fee 代表了交易股票的手续费用。你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。返回获得利润的最大值。注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。解题思路:常见股票买卖问题的动态规划,分为持有和不持有,只是在卖出的时候需要减去手续费,另外因为在同一天买卖一定是亏损的,所有不需要用额外的变量原创 2020-12-11 20:18:32 · 82 阅读 · 0 评论 -
2020-12-11
题目描述:给定一个非负整数数组,a1, a2, …, an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。返回可以使最终数组和为目标数 S 的所有添加符号的方法数。解题思路一:动态规划,遍历所有可以取到的值,通过对当前值进行加和减进行转移,代码如下:class Solution: def findTargetSumWays(self, nums: List[int], S: int) -> int:原创 2020-12-11 13:39:53 · 220 阅读 · 0 评论 -
646. 最长数对链
题目描述:给出 n 个数对。 在每一个数对中,第一个数字总是比第二个数字小。现在,我们定义一种跟随关系,当且仅当 b < c 时,数对(c, d) 才可以跟在 (a, b) 后面。我们用这种形式来构造一个数对链。给定一个数对集合,找出能够形成的最长数对链的长度。你不需要用到所有的数对,你可以以任何顺序选择其中的一些数对来构造。解题思路:先按照第一个数对数组排序,然后依次遍历数组,如果当前pair的第一个数组大于栈顶元素的第二个数,直接入栈,否则看pair的第二个元素是否小于栈顶元素的第二个元素,原创 2020-12-10 18:55:09 · 108 阅读 · 1 评论 -
583. 两个字符串的删除操作
题目描述:给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。解题思路:动态规划,和最长公共子序列相似,根据当前结尾的两个字符是否相等选择不同的转移方式,代码如下:class Solution: def minDistance(self, word1: str, word2: str) -> int: n1, n2 = len(word1), len(word2) dp原创 2020-12-10 16:36:09 · 126 阅读 · 0 评论 -
343. 整数拆分
题目描述:给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。解题思路一:动态规划,求得从2到n的每一个数的最大拆分情况,然后dp[n]可以由前面的子问题的解转移得到,因为拆分必须要拆成至少两个数,因此可能有些情况不拆分得到的乘积更大,因此转移一共要考虑四种情况,代码如下:class Solution: def integerBreak(self, n: int) -> int: dp = list(range(-1, n原创 2020-12-10 16:18:19 · 270 阅读 · 0 评论 -
53. 最大子序和
题目描述:给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。解题思路:动态规划,记录以每个数字结尾构成的连续子数组的最大和,然后取所有这些和中的最大值,因为状态转移过程只涉及到前一个连续子数组的最大和可以进行空间压缩,需要注意的是初始化条件res应该为一个尽可能的小的数,代码如下:class Solution: def maxSubArray(self, nums: List[int]) -> int: total, re原创 2020-12-10 15:14:38 · 122 阅读 · 0 评论 -
213. 打家劫舍 II
题目描述:你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,能够偷窃到的最高金额。解题思路:进行两遍动态规划,偷或者不偷第一家,偷第一家则不偷最后一家,不偷第一家则可以选择偷最后一家,代码如下:class Solution:原创 2020-12-10 15:07:38 · 160 阅读 · 0 评论 -
309. 最佳买卖股票时机含冷冻期
题目描述:给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):1.你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。2.卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。解题思路:根据题目描述,每天结束会有三种不同状态(1)持有股票(2)不持有股票,而且第二天是冷冻期(3)不持有股票,第二天不是冷冻期,可以根据每天的三种状态之间的转换完成状态转移,代码如下:cl原创 2020-09-09 20:47:09 · 120 阅读 · 0 评论 -
122. 买卖股票的最佳时机 II
题目描述:给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。解题思路一:只要当天价格高于昨天的价格,就将差值累积到最后结果,整个过程就是累积所有可以盈利的区间,代码如下:class Solution: def maxProfit(self, prices: List[int]) -> int: res原创 2020-12-10 10:31:33 · 92 阅读 · 0 评论 -
188. 买卖股票的最佳时机 IV
题目描述:给定一个整数数组 prices ,它的第 i 个元素 prices[i] 是一支给定的股票在第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。解题思路:动态规划,用has数组表示交易完毕后是持有状态,not_has表示交易完毕后不持有股票,下标i表示第i次交易完毕后,其中持有状态可能是当天买入,或者昨天就已经持有;不持有股票可能是当天卖出或者昨天就已经不持有股票了,根据这两种状态和交易次数原创 2020-12-10 09:39:07 · 102 阅读 · 0 评论 -
121. 买卖股票的最佳时机
题目描述:给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。解题思路:遍历整个数组,记录下过程中的最小值,计算当天的股票价格和到目前为止的股票最低价格,就是在当天卖出可以获得的最大收益,整个过程的收益最大值就是最终能够获得的最大利润,代码如下:class Solution: def maxProfit(self, prices: List[int]) -> int:原创 2020-12-09 21:30:14 · 101 阅读 · 0 评论 -
650. 只有两个键的键盘
题目描述:最初在一个记事本上只有一个字符 ‘A’。你每次可以对这个记事本进行两种操作:Copy All (复制全部) : 你可以复制这个记事本中的所有字符(部分的复制是不允许的)。Paste (粘贴) : 你可以粘贴你上一次复制的字符。给定一个数字 n 。你需要使用最少的操作次数,在记事本中打印出恰好 n 个 ‘A’。输出能够打印出 n 个 ‘A’ 的最少操作次数。解题思路一:由每一个当前得到结果不断的复制得到更长的结果,然后取所有的操作次数中最少的,代码如下:class Solution:原创 2020-12-09 20:10:08 · 104 阅读 · 0 评论 -
72. 编辑距离
题目描述:给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。你可以对一个单词进行如下三种操作:插入一个字符删除一个字符替换一个字符解题思路:动态规划,求得word1和word2的前缀子串两两之间的编辑距离,可得到最终word1和word2之间的编辑距离,如果当前两个子串的的末尾字符相同,那么dp[i][j]=dp[i-1][j-1],如果不相等,那么可以改变其中任意一个字符、删除任意一个字符或者插入一个字符,其中插入一个字符等价于删除一个原创 2020-12-09 18:47:18 · 101 阅读 · 0 评论 -
474. 一和零
题目描述:给你一个二进制字符串数组 strs 和两个整数 m 和 n 。请你找出并返回 strs 的最大子集的大小,该子集中 最多 有 m 个 0 和 n 个 1 。如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。解题思路:这个也是一个背包问题,只是现在????有0和1两种容量需要考虑,因此有三维动态规划来考虑,代码如下:class Solution: def findMaxForm(self, strs: List[str], m: int, n: int) -&g原创 2020-12-01 17:34:14 · 170 阅读 · 0 评论 -
416. 分割等和子集
题目描述:给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。注意:每个数组中的元素不会超过 100数组的大小不会超过 200解题思路:动态规划,转化为背包问题,从列表中选择一些数使得他们的和等于总和的一半,代码如下:class Solution: def canPartition(self, nums: List[int]) -> bool: total = sum(nums) if total % 2: re原创 2020-12-08 17:35:35 · 133 阅读 · 0 评论 -
1143. 最长公共子序列
题目描述:给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度。一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。两个字符串的「公共子序列」是这两个字符串所共同拥有的子序列。若这两个字符串没有公共子序列,则返回 0。解题思路:动态规划,用dp[i][j],表示text1前i个字符和t原创 2020-12-08 16:27:22 · 121 阅读 · 0 评论 -
139. 单词拆分
题目描述:给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。说明:拆分时可以重复使用字典中的单词。你可以假设字典中没有重复的单词。解题思路:trie+动态规划,前缀树用来快速查找当前字符串是否在字典中,dp数组用来记录哪些子串的位置可以用字典中单词构成,代码如下:class Solution: def wordBreak(self, s: str, wordDict: List[str]) -> bool:原创 2020-12-07 11:39:39 · 116 阅读 · 0 评论 -
279. 完全平方数
题目描述:给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。解题思路:动态规划,只是要分情况讨论,不是每一个位置都可以由前两个位置得到,代码如下:class Solution: def numSquares(self, n: int) -> int: dp = [float('inf')] * (n+1) dp[0] = 0 for i in range(1,原创 2020-12-07 10:56:59 · 93 阅读 · 0 评论 -
279. 完全平方数
题目描述:给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。解题思路:动态规划,只是转移的状态从固定的变为小于等于当前值的所有平方数,代码如下:class Solution: def numSquares(self, n: int) -> int: dp = [float('inf')] * (n+1) dp[0] = 0 for i in range(1,原创 2020-12-07 10:12:48 · 107 阅读 · 0 评论 -
221. 最大正方形
题目描述:在一个由 ‘0’ 和 ‘1’ 组成的二维矩阵内,找到只包含 ‘1’ 的最大正方形,并返回其面积。解题思路:如果matrix[i][j]=='0',那么(i, j)处可以构成的最大正方形面积为1,否则可以构成最大面积由上面、左边和左上角可以构成的最大面积决定,边长为这三个位置面积最下的边长+1,代码如下:class Solution: def maximalSquare(self, matrix: List[List[str]]) -> int: m, n = le原创 2020-12-06 15:56:56 · 120 阅读 · 0 评论 -
542. 01 矩阵
题目描述:给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。两个相邻元素间的距离为 1 。解题思路:对每个1都去找最近的0,他们只可能来自四个方向,左上角,右上角,左下角,右下角,每次都只考虑一个方向,然后当前的解可以从已经求解的部分得到,例如,对于来自左上角的0,当前位置的解只能来自左边的点和上面的点,因为四个方向实际上有重复,因此只进行两次遍历,遍历左上角和右下角即可,详细证明见LeetCode,代码如下:class Solution: def updateMatrix原创 2020-12-06 13:43:11 · 109 阅读 · 0 评论 -
64. 最小路径和
题目描述:给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。说明:每次只能向下或者向右移动一步。解题思路:因为只能向下或者向右,因此每个位置的最短路径的转移过程只能从上面或者左边,每次都取总和最小的那条路径进行累积,代码如下:class Solution: def minPathSum(self, grid: List[List[int]]) -> int: m, n = len(grid), len(gr原创 2020-12-06 12:11:25 · 92 阅读 · 0 评论 -
413. 等差数列划分
题目描述:如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。例如,以下数列为等差数列:1, 3, 5, 7, 97, 7, 7, 73, -1, -5, -9以下数列不是等差数列。1, 1, 2, 5, 7数组 A 包含 N 个数,且索引从0开始。数组 A 的一个子数组划分为数组 (P, Q),P 与 Q 是整数且满足 0<=P<Q<N 。如果满足以下条件,则称子数组(P, Q)为等差数组:元素 A[P], A[p + 1], …, A[Q原创 2020-12-06 11:38:38 · 180 阅读 · 0 评论 -
1641. 统计字典序元音字符串的数目
题目描述:给你一个整数 n,请返回长度为 n 、仅由元音 (a, e, i, o, u) 组成且按 字典序排列 的字符串数量。字符串 s 按 字典序排列 需要满足:对于所有有效的 i,s[i] 在字母表中的位置总是与 s[i+1] 相同或在 s[i+1] 之前。解题思路:用dp[i][j]表示以i结尾的长度为j的字符串,他的解全部可以由长度为j-1的字符串递推过来,为长度为j-1且结尾字符的字母顺序在i前面或者和i相等,然后同样的方法写出dp[i+1][j]的递推式,两式相减可以得到简化的递推式,dp[原创 2020-12-06 10:27:23 · 189 阅读 · 0 评论 -
837. 新21点
题目描述:爱丽丝参与一个大致基于纸牌游戏 “21点” 规则的游戏,描述如下:爱丽丝以 0 分开始,并在她的得分少于 K 分时抽取数字。 抽取时,她从 [1, W] 的范围中随机获得一个整数作为分数进行累计,其中 W 是整数。 每次抽取都是独立的,其结果具有相同的概率。当爱丽丝获得不少于 K 分时,她就停止抽取数字。 爱丽丝的分数不超过 N 的概率是多少?解题思路:动态规划,遍历所有可能的抽签过程,最大分数为N,然后统计所有最后一次抽签分数累计到K和N之间的情况的概率,这种方法会超时,代码如下:cla原创 2020-12-04 15:09:34 · 137 阅读 · 0 评论 -
321. 拼接最大数
题目描述:给定长度分别为 m 和 n 的两个数组,其元素由 0-9 构成,表示两个自然数各位上的数字。现在从这两个数组中选出 k (k <= m + n) 个数字拼接成一个新的数,要求从同一个数组中取出的数字保持其在原数组中的相对顺序。求满足该条件的最大数。结果返回一个表示该最大数的长度为 k 的数组。说明: 请尽可能地优化你算法的时间和空间复杂度。解题思路:(1)分别求出两个数组的最大子序列,使得两个子序列长度之和为k,两个数组的子序列长度组合最大有(k+1)中情况,最大子序列可以用单调栈解决原创 2020-12-04 11:12:26 · 250 阅读 · 0 评论 -
629. K个逆序对数组
题目描述:给出两个整数 n 和 k,找出所有包含从 1 到 n 的数字,且恰好拥有 k 个逆序对的不同的数组的个数。逆序对的定义如下:对于数组的第i个和第 j个元素,如果满i < j且 a[i] > a[j],则其为一个逆序对;否则不是。由于答案可能很大,只需要返回 答案 mod 109 + 7 的值。解题思路:思路详解见解析class Solution: def kInversePairs(self, n: int, k: int) -> int: dp原创 2020-12-03 22:20:01 · 150 阅读 · 0 评论 -
787. K 站中转内最便宜的航班
题目描述:有 n 个城市通过 m 个航班连接。每个航班都从城市 u 开始,以价格 w 抵达 v。现在给定所有的城市和航班,以及出发城市 src 和目的地 dst,你的任务是找到从 src 到 dst 最多经过 k 站中转的最便宜的价格。 如果没有这样的路线,则输出 -1。解题思路一:动态规划,只需要考虑从src出发的所有路线,经过最多K次中转到达目的地的最小价格。达到每个地方的最小价格是这一次不中转和从其他地方中转一次到达当前位置的价格中较小的那一个,代码如下:class Solution:原创 2020-12-02 17:44:59 · 179 阅读 · 0 评论 -
940. 不同的子序列 II
题目描述:给定一个字符串 S,计算 S 的不同非空子序列的个数。因为结果可能很大,所以返回答案模 10^9 + 7.解题思路:详见官方解析,代码如下:class Solution: def distinctSubseqII(self, S: str) -> int: BASE = int(1e9+7) size = len(S) dp = [0] * (size+1) dp[0] = 1 last = [-1原创 2020-12-02 10:51:41 · 124 阅读 · 0 评论 -
1458. 两个子序列的最大点积
题目描述:给你两个数组 nums1 和 nums2 。请你返回 nums1 和 nums2 中两个长度相同的 非空 子序列的最大点积。数组的非空子序列是通过删除原数组中某些元素(可能一个也不删除)后剩余数字组成的序列,但不能改变数字间相对顺序。比方说,[2,3,5] 是 [1,2,3,4,5] 的一个子序列而 [1,5,3] 不是。解题思路:动态规划dp[i][j]表示nums1[:i+1]和nums2[:j+1]的长度相同的非空子序列的最大点积,他的结果一共分为三种情况(1)最大点积没有用到nums原创 2020-12-01 20:21:01 · 181 阅读 · 0 评论 -
978. 最长湍流子数组
题目描述:当 A 的子数组 A[i], A[i+1], …, A[j] 满足下列条件时,我们称其为湍流子数组:若 i <= k < j,当 k 为奇数时, A[k] > A[k+1],且当 k 为偶数时,A[k] < A[k+1];或 若 i <= k < j,当 k 为偶数时,A[k] > A[k+1] ,且当 k 为奇数时, A[k] < A[k+1]。也就是说,如果比较符号在子数组中的每个相邻元素对之间翻转,则该子数组是湍流子数组。返回 A 的最原创 2020-12-01 18:58:40 · 130 阅读 · 0 评论
分享