- 博客(126)
- 收藏
- 关注
原创 动态规划---最长回文子序列
如果s[i]=s[j],那么可以把s[i],s[j]加入到最长回文子序列中,dp[i][j]=dp[i+1][j-1]+2。取两种情况值最大的那一个,dp[i][j]=max(dp[i][j-1],dp[i+1][j])(1)把s[i]加入最长回文子序列中,dp[i][j]=dp[i][j-1](2)把s[j]加入最长回文子序列中,dp[i][j]=dp[i+1][j]dp[i][j]代表区间为[i,j]的字符串s的最长回文子序列的长度。根据dp数组含义,dp[i][i]=1,其他元素初始化0。
2024-09-20 09:37:18
272
原创 动态规划---回文子串
(3)j-i>1,要确定区间[i+1,j-1]的字符串是不是回文子串,如果是,那么dp[i][j]=true。dp[i][j]代表字符串区间[i,j](左闭右闭)的字符是不是回文子串(true,false)=s[j],一定不是回文子串,dp[i][j]=false。(1)j-i=0,是回文子串,dp[i][j]=true。(2)j-i=1,是回文子串,dp[i][j]=true。是字符串中的由连续字符组成的一个序列。根据递推公式,需要从下到上,从左到右遍历。是正着读和倒过来读一样的字符串。
2024-09-19 14:13:04
320
原创 动态规划---编辑距离
对word1执行替换操作,就是word1替换word1[i-1],使其与word2[j-1]相同,在word1[i-1]=word2[j-1]时,有dp[i][j]=dp[i-1][j-1],现在需要在此基础上增加一次替换操作,所以有公式:dp[i][j]=dp[i-1][j-1]+1。综上:dp[i][j]=min(dp[i-1][j]+1,dp[i][j]=dp[i][j-1]+1,dp[i][j]=dp[i-1][j-1]+1)根据递推公式,我们需要初始化,dp[i][0],dp[0][j]
2024-09-19 13:10:30
312
原创 动态规划---两个字符串的删除操作
如果word1[i-1]!=word2[j-1],那么可以删除word1[i-1],或者可以删除word2[j-1],或者两个字符串都删除字符,所有有dp[i][j]=min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+2)根据递推公式,需要初始化dp[i][0],dp[0][j],根据dp数组的含义有dp[i][0]=i,dp[0][j]=j。如果word1[i-1]=word2[j-1],那么两个字符串都不用删除,dp[i][j]=dp[i-1][j-1]
2024-09-18 13:59:02
295
原创 动态规划---不同的子序列
根据递推公式,我们需要初始化dp[i][0],含义是以下标i-1结尾的s子序列随便删除元素出现空字符串的个数,即个数为1(全删),初始化dp[0][j],含义是空字符串s随便删除元素出现字符串t的个数,即个数为0。如果s[i-1]=t[j-1],那么可以用s[i-1]匹配,个数为dp[i-1][j-1];可以不用s[i-1]来匹配,个数为dp[i-1][j]dp[i][j]代表以下标i-1结尾的s子序列中出现以下标j-1结尾的字符串t的个数。=t[j-1],那么个数为dp[i-1][j]
2024-09-18 09:34:44
194
原创 动态规划---判断子序列
t[j-1],那么将t回退(这就是两题的不同之处),dp[i][j]=dp[i][j-1]字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。如果s[i-1]=t[j-1],那么找到了一个公共元素,dp[i][j]=dp[i-1][j-1]+1。dp[i][j]代表[0,i-1]长度的字符串s,[0.j-1]长度的字符串t的最长公共子序列。外层for循环遍历字符串s,内层for循环遍历字符串t,从小到大遍历。1.确定dp数组及含义。
2024-09-16 09:50:53
265
原创 动态规划---不相交的线
如果nums1[i]不等于nums2[j],那么dp[i][j]=max(dp[i-1][j],dp[i][j-1])如果nums1[i]=nums2[j],那么遇到了一个相同的数字,dp[i][j]=dp[i-1][j-1]+1。dp[i][j]代表长度[0,i-1]的数组nums1,长度[0,j-1]的数组nums2的最长公共子序列长度。外层for循环遍历nums1数组,内层for循环遍历nums2数组,从小到大遍历。请注意,连线即使在端点也不能相交:每个数字只能属于一条连线。1.确定dp数组及含义。
2024-09-15 16:17:28
187
原创 动态规划---最长公共子序列
如果text1[i-1]与text2[j-1]不相同,那么就看text1[0,i-2]与text2[0,j-1]的最长公共子序列和text1[0,i-1]与text2[0,j-2]的最长公共子序列,取最大的,即dp[i][j]=max(dp[i-1][j],dp[i][j-1])如果text1[i-1]与text2[j-1]相同,那么找到了一个公共元素,dp[i][j]=dp[i-1][j-1]+1。外层遍历text1,内层遍历text2,从小到大遍历。,返回这两个字符串的最长。1.确定dp数组及含义。
2024-09-15 15:58:47
345
原创 动态规划---最长重复子数组
dp[i][j]代表下标以i-1结尾的nums1数组,下标以j-1结尾的nums2数组,最长重复子数组的长度。当nums1[i-1]=nums2[j-1]时,dp[i][j]=dp[i-1][j-1]+1。外层遍历nums1,内层遍历nums2。、长度最长的子数组的长度。题目:给两个整数数组。1.确定dp数组及含义。
2024-09-14 16:57:52
211
原创 动态规划---最长连续递增序列
如果nums[i]>nums[i-1],那么有dp[i]=dp[i-1]+1。dp[i]代表i及i之前最长连续递增序列的长度。给定一个未经排序的整数数组,找到最长且。,并返回该序列的长度。)确定,如果对于每个。就是连续递增子序列。1.确定dp数组及含义。
2024-09-14 09:59:41
258
原创 动态规划---最长递增子序列
用j来遍历0-i下标的所有元素,如果nums[j]<nums[i],则dp[i]=max(dp[i],dp[j]+1)是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。dp[i]代表i之前包括i结尾的最长递增子序列的长度。,找到其中最长严格递增子序列的长度。1.确定dp数组及含义。
2024-09-14 09:42:40
250
原创 动态规划---买卖股票的最佳时机含手续费
你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。思路:与题买卖股票的最佳时机(2)思路完全一致,只需在买股票时再多减去手续费即可。这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。代表了交易股票的手续费用。返回获得利润的最大值。
2024-09-13 13:49:09
164
原创 动态规划---最佳买卖股票时机含冷冻期
dp[i][0]的来源为:第i-1天就持有股票今天继续保持,第i-1天保持不持有股票状态今天买入,第i-1天是冷冻期今天买入。dp[i][1]的来源为:第i-1天是保持不持有状态今天继续保持不持有,第i-1天是冷冻期今天不买入。j=0:持有股票 j=1:保持不持有股票 j=2:今天卖出 j=3:冷冻期。dp数组为prices.length*4的数组,dp[i][j]代表第i天j状态下的最大收益。根据递推公式及数组含义,我们需要初始化dp[0][0]=-prices[0],其他元素为0。
2024-09-12 18:57:12
168
原创 动态规划---买卖股票的最佳时机(4)
dp[i][j+2]=max(dp[i-1][j+2],dp[i-1][j+1]+prices[i]) 不持有。dp[i][j+1]=max(dp[i-1][j+1],dp[i-1][j]-prices[i]) 持有。根据递推公式,需要初始化dp[0][j],j为奇数时,dp[0][j]=-prices[j];j为偶数时,dp[0][j]=0。j为0时代表无操作,j为偶数是代表第j/2次不持有股票,j为奇数时代表第j/2次持有股票。dp[i][j]代表第i天j状态下获得的最大收益。
2024-09-12 13:26:01
276
原创 动态规划---买卖股票的最佳时机(3)
dp数组是一个prices.length*5的二维数组,dp[i][j]代表第i天j状态下能获得的最大利润。最后返回最后一个天第二次不持有的dp数值,因为买卖两次的利润一定是最多的。dp[0][3]=-prices[0] 第0天买入又卖出再买入。dp[0][1]=-prices[0] 第0天买入。dp[0][4]=0 第0天买入又卖出再买入再卖出。dp[0][0]=0 第0天没有操作。dp[0][2]=0 第0天不买入不持有。j=2: 第一次不持有股票。j=4: 第二次不持有股票。
2024-09-11 13:09:53
212
原创 动态规划---买卖股票的最佳时机(2)
dp数组是一个prices.length*2的二维数组,dp[i][0]代表第i天持有股票(手里有股票,不一定是今天买的)获得的最大收益,dp[i][1]代表不持有股票(手里没股票,不一定是今天卖的)获得的最大收益。dp[i][0]=max(dp[i-1][0],dp[i-1][1]-prices[i]) (今天没买手持之前买的,今天买的股票)根据递推公式,i由i-1推出,那么要初始化dp[0][0]=-prices[0],dp[0][1]=0。在每一天,你可以决定是否购买和/或出售股票。
2024-09-11 09:41:24
253
原创 动态规划---买卖股票的最佳时机
dp[i][1]代表第i天不持有(维持i-1天的不持有状态或者卖出之前的股票)股票的最大收益。dp[i][0]代表第i天持有股票(买入当天或者维持i-1天的持有状态)的最大收益。返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回。根据递推公式,我们要初始化dp[0][0],dp[0][1]设计一个算法来计算你所能获取的最大利润。买入这只股票,并选择在。1.确定dp数组及含义。
2024-09-10 10:01:29
198
原创 动态规划---打家劫舍(3)
每一个节点有偷和不偷两种状态,那么递归函数的返回值就是一个长度为2的int数组,其实这里返回的数组就是dp数组,dp数组的第一个元素记录不偷该节点可以得到的金钱值,第二个元素记录偷该节点可以得到的金钱值。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。本题涉及到二叉树,处理二叉树的方法必不可少的就是递归与回溯,接下来结合递归三部曲与动态规划五部曲来综合分析问题。如果不偷当前节点,那么左右孩子就可以偷,选一个最大的偷。通过递归左节点,得到左节点偷与不偷的金钱。
2024-09-10 09:39:03
347
原创 动态规划---打家劫舍(2)
思路:本题与上一题的区别在于本题是一个环,上一题就是普通数组。那么把环分成两部分处理,一个只考虑头不考虑尾,一个只考虑尾不考虑头,就把题目转换成上一题的情况了。你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都。,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,给定一个代表每个房屋存放金额的非负整数数组,计算你。,今晚能够偷窃到的最高金额。
2024-09-09 09:55:59
245
原创 动态规划---打家劫舍
如果偷下标为i的房间,那么dp[i]=dp[i-2]+nums[i],即找出下标i-2房间以内的房屋可以偷窃到的最高金额,再加上下表为i的房间的金额;每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果不偷下标为i的房间,那么dp[i]=dp[i-1],即只考虑下标i-1以内的房屋可以偷窃的最高金额。dp数组是一维数组,dp[i]代表考虑下标i(包括i)以内的房屋可以偷窃到的最高金额。决定dp[i]偷不偷取决于下标i-1和i-2的dp数组值。1.确定dp数组及含义。
2024-09-09 09:35:37
225
原创 动态规划---完全平方数
由于递推公式中我们取min,因此初始化数组应该为整数最大值,这样后面的递推中才能被被覆盖。dp[0]=0,表示和为0的完全平方数的最小数量为0。是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。思路:本题 属于完全背包问题,完全平方数属于物品,可重复取用,整数mn属于背包。n=5,初始化dp=[0,max,max,max,max,max]dp数组为一维数组,dp[i]代表和为i的完全平方数的最小数量。本题求得是组合数,因此先遍历物品再遍历背包容量。的完全平方数的最少数量。
2024-09-07 15:26:48
384
原创 动态规划---单词拆分
本题我们求的属于排列数,因为用字典中的元素凑成字符串是有顺序的。因此遍历顺序为先遍历背包(字符串),再遍历物品(字符串列表)。思路:本题属于完全背包问题,字符串s的长度为背包容量,字符串列表wordDict中的每一个元素相当于物品。如果dp[j]=true,j<i,且在[j,i]这个区间的子串出现在字典里,那么dp[i]=true。dp数组为元素类型是布尔型的一维数组,dp[i]代表长度为i的字符串可否由字符串列表里的元素拼成。不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。
2024-09-07 14:58:17
242
原创 动态规划---零钱兑换
由于递推公式是在dp[j]与dp[j-coins[i]]+1中取最小值,那么初始化dp就应该是最大值Integer.MAX_VALUE。dp[0]代表总金额为0时最少的硬币数,应该为0。要加入一个coins[i]达到总金额j,那么加入后最少硬币个数为1+dp[j-coins[i]]本题属于完全背包问题,但所求方案可以是排列数也可以是组合数,都不影响最少硬币数。dp数组是一维数组,dp[j]代表凑成总金额j所需的最少硬币个数。因此遍历序列可以是先遍历物品再遍历背包容量,也可以反过来。1.确定dp数组及含义。
2024-09-06 11:11:49
268
原创 动态规划---组合总和(4)
dp[0]=1,意思是数值总和为0的排列方案有一种。如果dp[0]=0,那么接下来的推导都为0。dp数组是一维数组(滚动数组),dp[j]代表数值总和为target的排列方案有多少。外层for循环正序遍历背包容量,内层for循环正序遍历物品(nums)。输入:nums=[1,2,3],target=4。题目数据保证答案符合 32 位整数范围。思路:本题求的是排列方案。1.确定dp数组及含义。5.举例推导dp数组。
2024-09-06 10:16:00
325
原创 动态规划---零钱兑换(2)
不可以,先遍历物品,再遍历背包容量,dp数组存储的是方案组合数;先遍历背包容量,再遍历物品,dp数组存储的就是方案排列数。01背包问题中内层倒序遍历保证了物品不会被重复加入,而本题为完全背包问题,物品可以多次取,因此采用正序。dp[j]就是所有的dp[j-coins[i]]相加,所以递归公式为dp[j]+=dp[j-coins[i]]dp[0]=1,可以理解为凑成金额为0的货币组合数为1。如果dp[0]=0,那么后续的推导都是0。dp数组为一维数组,dp[j]代表总额为j的货币组合数。
2024-09-05 14:29:18
354
原创 动态规划---一和零
在遍历过程中取最大值,所以递推公式为dp[i][j]=max(dp[i][j],dp[i-zeroNum][j-oneNum]+1)dp数组需要有两个维度,i来遍历数字0,j来遍历数字1。dp[i][j]表示最多有i个数字0,j个数字1时最大子集的长度。dp[i][j]可以由前一个str里的字符串推导出来,str里的字符串有zeroNum个0,oneNum个1。dp[i][j]就可以是dp[i-zeroNum][j-oneNum]+1。的最大子集的长度,该子集中。给你一个二进制字符串数组。
2024-09-05 12:53:12
322
原创 动态规划---目标和
假设加法的总和为left,减法的总和就是sum-left。该问题就转化为物品重量数组为nums,物品价值数组为nums,背包最大容量为left,求背包装满有几种方法.如果(sum+target)/2不为整数,那么这组数不能构成运算结果为target的表达式。只要加入nums[i],凑成重量j,有dp[j-nums[i]]种方法。如果target的绝对值大于sum,那么这组数不能构成运算结果为target的表达式。dp数组为一维数组(滚动数组),dp[j]表示装满容量为j的书包,有多少种方法。
2024-09-04 14:46:07
178
原创 动态规划---最后一块石头的重量(2)
最后dp[target]的值就是容量为target的背包所能背的最大价值,那么分成两堆的石头,一堆重量为dp[target],一堆为sum-dp[target],返回(sum-dp[target])-dp[target]。dp数组的长度为所有是同重量的一半,因为dp[j]中的j表示容量,那么最大容量就是所有石头重量的一半(我们要把石头尽可能均分成两堆)。dp数组为一维数组(滚动数组),dp[j]表示容量为j的背包能装的最大价值。把这一堆石头尽可能均分成两堆,两堆的重量之差就是剩余最小的可能重量。
2024-09-04 09:40:24
360
原创 动态规划---01背包问题理论总结
观察递推公式,dp[i][j]是靠i-1那一行的数据推导出来的,先遍历物品后遍历背包重量的情况下计算i行时i-1行已经计算过了,先遍历背包重量后遍历物品的情况下dp[i-1] [j],dp[i-1] [ j-weight[i] ]都已经计算过了。:二维dp中计算dp[i][j]使用的一直是i-1行的数据,没有受到i行数据的影响,而一维dp中计算i行的dp[j]初始化是i-1行数据,但在推导的过程中会逐渐覆盖掉i-1行的值,计算时会受到i行数据的干扰。结论是:先遍历物品也可以,先遍历背包重量也可以。
2024-09-03 20:41:37
467
原创 动态规划---分割等和子集
dp为二维数组时dp[i][j]=max(dp[i-1][j],dp[i][j-weight[i]]+value[i]),本题中weight数组=value数组=nums数组。dp[i][j]的含义是把0~i的物品尽量放入到容量为j的背包中,背包的最大价值。dp数组为一维数组(滚动数组),等价于dp数组为二维数组时把i-1行的数据拷贝到i行,把矩阵压缩为一行。例如nums=[1,5,11,5],dp=[0,1,1,1,1,5,6,6,6,6,10,11]如果有负数,要将对应的dp元素初始化为负无穷。
2024-09-03 17:06:52
316
原创 动态规划---不同路径(2)
对于obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]],dp数组为[[1,1,1],[1,0,1],[1,1,2]]当(i,j)位置没有障碍时,dp[i][j]=dp[i-1][j]+dp[i][j-1]。1.确定dp数组及含义。dp数组是一个二维数组,dp[i][j]表示从起点到(i,j)的不同路径条数。第一行第一列都初始化为1,如果有障碍,则障碍之后(之下)的位置初始化为0。现在考虑网格中有障碍物。机器人试图达到网格的右下角。网格中的障碍物和空位置分别用。
2024-09-03 09:53:22
232
原创 贪心算法---不同路径
到达(i,j)位置可以从(i-1,j)向下走一步或者从(i,j-1)向右走一步。故dp[i][j]=dp[i-1][j]+dp[i][j-1]。1.确定dp数组及含义。dp数组需要是一个二维数组,dp[i][j]代表从起始位置到下标为(i,j)位置的不同路径条数。3.dp数组初始化。因为每一次只能向右或者向下走,所以第一行和第一列要初始化为1。机器人试图达到网格的右下角。问总共有多少条不同的路径?5.举例推导dp数组。从左到右从上到下遍历。
2024-09-02 14:07:49
314
原创 动态规划---使用最小花费爬楼梯
一次可爬一层或两层,到达第i层可以从i-1层再爬一层到达,或者从i-2层再爬两层到达。题目中表达可以从第0层或者第一层出发,故dp[0]=0,dp[1]=0。一旦你支付此费用,即可选择向上爬一个或者两个台阶。1.确定dp数组及含义。使用一维数组即可,dp[i]表示爬到第i层的最小花费。],那么dp=[0,0,1,2,2,3,3,4,4,5,6]请你计算并返回达到楼梯顶部的最低花费。5.举例推导dp数组。
2024-09-02 09:50:01
250
原创 动态规划---爬楼梯
dp[i-1]记录爬到i-1阶的方法种类,再爬1阶就到了i阶;dp[i-2]记录爬到i-2阶的方法种类,再爬2阶就到了i阶。所以dp[i]=dp[i-1]+dp[i-2]。5.举例推导dp数组。例如n=5,dp数组序列从下标1开始依次为[1,2,3,5,8]3.dp数组初始化。dp[0]没有意义,可以不管,dp[1]=1,dp[2]=2。1.确定dp数组及下标的含义。dp[i]记录爬到i阶有多少种方法。从前往后遍历,i值从3到n依次求得dp[i]你有多少种不同的方法可以爬到楼顶呢?
2024-09-01 13:35:08
225
原创 动态规划---斐波那契数
例如n=5时,dp数组应是如下序列[0,1,1,2,3,5]。如果代码写出来发现结果不对,就把dp数组打印出来看看是否一致。从前往后遍历,按照i值从小到大依次求结果,直至i=n。F(n) = F(n - 1) + F(n - 2),其中 n > 1。1.确定dp数组以及下标的含义。本题中dp[i]存储F(i)计算结果。初始化dp[0]=0,dp[1]=1。开始,后面的每一项数字都是前面两项数字的和。动态规划五部曲:使用一个一维dp数组来存储每一步的结果。
2024-09-01 13:19:12
183
原创 贪心算法---监控二叉树
叶结点上不能放摄像头,在叶结点的父亲节点上开始放摄像头。0表示无覆盖,1表示有摄像头,2表示有覆盖。单层递归逻辑只需根据节点的左右孩子情况来设置节点的状态,保证两个孩子都能被监控。空节点的状态不能是无覆盖,又不能放摄像头,因此空姐点的状态为有覆盖。递归的终止条件应该是遇到空节点,返回2(有覆盖)。2.左右节点至少一个为无覆盖,则节点状态为有摄像头。3.左右节点至少一个为有摄像头,则节点状态为有覆盖。4.头节点状态为无覆盖时,应在头节点位置放摄像头。1.左右节点都有覆盖,则节点状态为无覆盖。
2024-08-31 15:30:38
372
原创 贪心算法---单调递增的数字
对于非递增的相邻位两个数字x和y,有x>y,如98。处理方法应该是把x-1,y赋值为9,如比98小的最大单调递增整数为89。代码技巧为使用flag记录从哪里开始赋值为9。关于遍历顺序,应采用从后到前遍历,这样才能重复利用上一次比较的结果。String.valueOf(a)可以将不同类型的数据a转换为字符串类型。Integer.parseInt(string)可以将字符串转换为整数。当且仅当每个相邻位数上的数字。的最大数字,且数字呈。时,我们称这个整数是。
2024-08-31 13:25:46
574
原创 贪心算法---合并区间
思路:对数组按照元素的start数值升序排列,与前几题相似先判断区间是否重叠,不重叠的直接加入结果集,重叠的更新最大右边界(合并操作)。一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。表示若干个区间的集合,其中单个区间为。请你合并所有重叠的区间,并返回。
2024-08-30 11:02:35
495
原创 贪心算法---划分字母区间
先遍历一遍字符串记录所有字母最后出现的下标,再遍历一遍字符串更新字符出现的最远下标,如果找到字符最远出现的位置下标和当前下标相等,则找到了分割点。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是。返回一个表示每个字符串片段的长度的列表。
2024-08-30 10:36:50
470
原创 贪心算法---无重叠区间
思路:将intervals数组按照左边界从小到大进行排序,用count记录无交叉的区间数量。遍历数组,如果正在遍历的区间与上一个区间有重叠,则将该区间的右边界更新为两个区间的最小右边界。如果正在遍历的区间与上一个区间无重叠,则count+1。最后用数组长度减去count就是无重叠区间数量。需要移除区间的最小数量,使剩余区间互不重叠。题目:给定一个区间的集合。
2024-08-29 17:09:39
447
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人