自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(44)
  • 收藏
  • 关注

原创 代码随想录

t[j - 1]),此时相当于t要删除元素,t如果把当前元素t[j - 1]删除,那么dp[i][j] 的数值就是 看s[i - 1]与 t[j - 2]的比较结果了,即:dp[i][j] = dp[i][j - 1];if (s[i - 1] == t[j - 1]),那么dp[i][j] = dp[i - 1][j - 1] + 1;从递推公式可以看出dp[i][j]都是依赖于dp[i - 1][j - 1] 和 dp[i][j - 1],所以dp[0][0]和dp[i][0]是一定要初始化的。

2024-04-25 17:10:51 650

原创 代码随想录

如果text1[i - 1] 与 text2[j - 1]不相同,那就看看text1[0, i - 2]与text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]与text2[0, j - 2]的最长公共子序列,取最大的。但dp[i][0] 和dp[0][j]要初始值,因为 为了方便递归公式dp[i][j] = dp[i - 1][j - 1] + 1;即当A[i - 1] 和B[j - 1]相等的时候,dp[i][j] = dp[i - 1][j - 1] + 1;

2024-04-23 23:39:37 918

原创 代码随想录

为什么一定表示 “以nums[i]结尾的最长递增子序” ,因为我们在 做 递增比较的时候,如果比较 nums[j] 和 nums[i] 的大小,那么两个递增子序列一定分别以nums[j]为结尾 和 nums[i]为结尾, 要不然这个比较就没有意义了,不是尾部元素的比较那么 如何算递增呢。因为本题要求连续递增子序列,所以就只要比较nums[i]与nums[i - 1],而不用去比较nums[j]与nums[i] (j是在0到i之间遍历)。即:dp[i] = dp[i - 1] + 1;

2024-04-23 02:35:11 692

原创 代码随想录

如果i为1,第1天买入股票,那么递归公式中需要计算 dp[i - 1][1] - prices[i] ,即 dp[0][1] - prices[1],那么大家感受一下 dp[0][1] (即第0天的状态二)应该初始成多少,只能初始为0。那么dp[i][0] = max(dp[i - 1][0], dp[i - 1][3] - prices[i], dp[i - 1][1] - prices[i]);今天卖出了股票(状态三),同上分析,dp[0][2]初始化为0,dp[0][3]也初始为0。

2024-04-21 18:16:20 974

原创 代码随想录

同样dp[i][1]取最大的,dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);那么dp[i][0]应该选所得现金最大的,所以dp[i][0] = max(dp[i - 1][0], -prices[i]);一定是选最大的,所以 dp[i][1] = max(dp[i-1][0] - prices[i], dp[i - 1][1]);那么dp[i][1]究竟选 dp[i-1][0] - prices[i],还是dp[i - 1][1]呢?

2024-04-19 19:41:16 718

原创 代码随想录

如果不偷当前节点,那么左右孩子就可以偷,至于到底偷不偷一定是选一个最大的,所以:val2 = max(left[0], left[1]) + max(right[0], right[1]);所以dp数组(dp table)以及下标的含义:下标为0记录不偷该节点所得到的的最大金钱,下标为1记录偷该节点所得到的的最大金钱。即:{不偷当前节点得到的最大金钱,偷当前节点得到的最大金钱}这里我们要求一个节点 偷与不偷的两个状态所得到的金钱,那么返回值就是一个长度为2的数组。通过递归左节点,得到左节点偷与不偷的金钱。

2024-04-16 18:51:07 386

原创 代码随想录

如果偷第i房间,那么dp[i] = dp[i - 2] + nums[i] ,即:第i-1房一定是不考虑的,找出 下标i-2(包括i-2)以内的房屋,最多可以偷窃的金额为dp[i-2] 加上第i房间偷到的钱。从dp[i]的定义上来讲,dp[0] 一定是 nums[0],dp[1]就是nums[0]和nums[1]的最大值即:dp[1] = max(nums[0], nums[1]);然后dp[i]取最大值,即dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);

2024-04-15 19:11:58 636

原创 代码随想录

凑足总额为j - coins[i]的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1就是dp[j](考虑coins[i])考虑到递推公式的特性,dp[j]必须初始化为一个最大的数,否则就会在min(dp[j - coins[i]] + 1, dp[j])比较的过程中被初始值覆盖。此时我们要选择最小的dp[j],所以递推公式:dp[j] = min(dp[j - i * i] + 1, dp[j]);所以遍历的内循环是正序。

2024-04-13 18:34:21 931

原创 代码随想录

dp[0]=1还说明了一种情况:如果正好选了coins[i]后,也就是j-coins[i] == 0的情况表示这个硬币刚好能选,此时dp[0]为1表示只选coins[i]存在这样的一种选法。那么 dp[0] = 1 有没有含义,其实既可以说 凑成总金额0的货币组合数为1,也可以说 凑成总金额0的货币组合数为0,好像都没有毛病。首先dp[0]一定要为1,dp[0] = 1是 递归公式的基础。下标非0的dp[j]初始化为0,这样累计加dp[j - coins[i]]的时候才不会影响真正的dp[j]

2024-04-12 18:17:34 836

原创 代码随想录

此时大家可以回想一下01背包的递推公式:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);所以递推公式:dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);完全背包中,两个for循环的先后循序,都不影响计算dp[j]所需要的值(这个值就是下标j之前所对应的dp[j])。dp[i][j] 就可以是 dp[i - zeroNum][j - oneNum] + 1。只不过物品的重量有了两个维度而已。

2024-04-12 01:55:31 918

原创 代码随想录

接下来就是如何初始化dp[j]呢,因为重量都不会是负数,所以dp[j]都初始化为0就可以了,这样在递归公式dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);其实也可以使用二维dp数组来求解本题,dp[i][j]:使用 下标为[0, i]的nums[i]能够凑满j(包括j)这么大容量的包,有dp[i][j]种方法。01背包的递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

2024-04-11 03:53:29 811

原创 代码随想录

其实从递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);所以递推公式:dp[i] += dp[j - 1] * dp[i - j];所以递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

2024-04-09 20:25:47 1170

原创 代码随想录

从递归公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 中可以看出,一定是从左到右一层一层遍历,这样保证推导dp[i][j]的时候,dp[i - 1][j] 和 dp[i][j - 1]一定是有数值。那么很自然,dp[i][j] = dp[i - 1][j] + dp[i][j - 1],因为dp[i][j]只有这两个方向过来。想要求dp[i][j],只能有两个方向来推导出来,即dp[i - 1][j] 和 dp[i][j - 1]。下标(0, j)的初始化情况同理。

2024-04-09 16:42:31 472

原创 代码随想录

中可以看出,dp[i]是依赖 dp[i - 1] 和 dp[i - 2],那么遍历的顺序一定是从前到后遍历的。所以我的原则是:不考虑dp[0]如何初始化,只初始化dp[1] = 1,dp[2] = 2,然后从i = 3开始递推,这样才符合dp[i]的定义。还有就是dp[i - 2],上i-2层楼梯,有dp[i - 2]种方法,那么再一步跳两个台阶不就是dp[i]了么。首先是dp[i - 1],上i-1层楼梯,有dp[i - 1]种方法,那么再一步跳一个台阶不就是dp[i]了么。

2024-03-30 22:48:43 345

原创 代码随想录

思路:首先转换成字符串,从后向前遍历,当我们遇到str[i-1]>str[i]的时候,str[i-1]-- ,flag = i .flag来记住从哪里开始要变成9。从后向前遍历332的数值变化为:332 ->329 -> 299。如果是以下情况,其实就是 左右孩子节点有一个有摄像头了,那么其父节点就应该是2(覆盖的状态)左孩子有覆盖,右孩子有覆盖,那么此时中间节点应该就是无覆盖的状态了。以上都处理完了,递归结束之后,可能头结点 还有一个无覆盖的情况。思路:后序遍历二叉树 ,头节点在主函数里专门判断。

2024-03-29 03:12:43 284

原创 代码随想录

思路:本题需要先按照左边界排序这样让区间尽可能的重叠,之后遍历判断i和i-1的区间是不是重叠,如何判断 如果i的左边界小于i-1的右边界,那么就是重叠了。我们的计数器+1,且我们要更新i的右边界,为什么要更新,因为当我们遍历到i+1区间时,我们要判断一下i+1是不是跟上两个区间也重叠。如何更新呢 i的右边界 = 取最小值(i的右边界,i-1的右边界)。思路:跟无重叠区间差不多,只是当区间重叠时我们要合并两个重叠的区间,怎么合并呢 让左边界就是i-1的左边界,右边界在两个区间的右边界中取最大值。

2024-03-28 22:02:50 161

原创 代码随想录

思路:第一种情况 收取面额为5的 直接FIVE++就好,第二种情况收取面额为10的,如果手头FIVE==0就无法找零 return false。思路:先对数组按身高从大到小排序,如果身高相同,按k值从小到大排,这样我们就先确定了一边。遍历数组,我们获取每个人的k值 在新数组中按照k值排序。如果按照k来从小到大排序,排完之后,会发现k的排列并不符合条件,身高也不符合条件,两个维度哪一个都没确定下来。那么按照身高h来排序呢,身高一定是从大到小排(身高相同的话则k小的站前面),让高个子在前面。

2024-03-27 00:01:21 125

原创 代码随想录

如果 ratings[i] > ratings[i + 1],此时candyVec[i](第i个小孩的糖果数量)就有两个选择了,一个是candyVec[i + 1] + 1(从右边这个加1得到的糖果数量),一个是candyVec[i](之前比较右孩子大于左孩子得到的糖果数量)。那么又要贪心了,局部最优:取candyVec[i + 1] + 1 和 candyVec[i] 最大的糖果数量,保证第i个小孩的糖果数量既大于左边的也大于右边的。全局最优:相邻的孩子中,评分高的孩子获得更多的糖果。

2024-03-25 23:31:38 227

原创 代码随想录

相当于(prices[3] - prices[2]) + (prices[2] - prices[1]) + (prices[1] - prices[0])。i 每次移动只能在 cover 的范围内移动,每移动一个元素,cover 得到该元素数值(新的覆盖范围)的补充,让 i 继续移动下去。如果移动下标达到了当前这一步的最大覆盖最远距离了,还没有到终点的话,那么就必须再走一步来增加覆盖范围,直到覆盖范围覆盖了终点。假如第 0 天买入,第 3 天卖出,那么利润为:prices[3] - prices[0]。

2024-03-24 03:39:00 244

原创 代码随想录

我们只需要在 这个坡度 摆动变化的时候,更新 prediff 就行,这样 prediff 在 单调区间有平坡的时候 就不会发生变化,造成我们的误判。思路:数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。情况2:这里我们可以写死,就是 如果只有两个元素,且元素不同,那么结果为 2。也要记录一个峰值,因为他是把之前相同的元素都删掉留下的峰值。全局最优:选取最大“连续和”

2024-03-23 08:53:39 212

原创 代码随想录

思路:排列问题跟组合问题不一样的点是:i 从0开始遍历而不是startindex,因为排列可以取前面的元素比如说【1,2】,【2,1】是2个排列。终止条件:我们在叶子节点收集结果,所以当path.size() == nums.size()时 就收集结果。而for循环是从0开始的,所以需要这一步。思路:本题跟子集2不一样,无法排序,也就是在去重上我们无法使用bool数组来去重,所以本题我们要使用set来去重。本题求子序列,很明显一个元素不能重复使用,所以需要startIndex,调整下一层递归的起始位置。

2024-03-21 06:23:21 228

原创 代码随想录

93 复原ip地址思路:本题跟分割回文串 差不多,还是三部曲本题明确要求只会分成4段,所以不能用切割线切到最后作为终止条件,而是分割的段数作为终止条件。pointNum表示逗点数量,pointNum为3说明字符串分成了4段了。因为ip的格式就是3个逗点分割4段。然后验证一下第四段是否合法,如果合法就加入到结果集里单层递归逻辑:在循环中 [startIndex, i] 这个区间就是截取的子串,需要判断这个子串是否合法。如果合法就在字符串后面加上符号表示已经分割。如果不合法就结束本层循环。

2024-03-20 02:51:11 315

原创 代码随想录

思路:本题我们要理解,每个组合中,每个数字只能用一次,但如果有相同的元素,在组合中可以使用。但不能包含重复的组合比如说 [10,1,2,7,6,1,5] 可以有【1,1,6】因为有2个1.所以本题我们需要一个used数组来判断你当前遍历的元素跟上一个是不是相同,且还是需要startindex来去重,因为本题candidates 中的每个数字在每个组合中只能使用一次。循环中,我们 定义了起始位置startIndex,那么 [startIndex, i] 就是要截取的子串。

2024-03-19 04:45:32 261

原创 代码随想录

216 组合总和3思路:本题就是在 1到9里面找n个和为k的组合,例如 k = 2,n = 4的话,就是在集合[1,2,3,4,5,6,7,8,9]中求 k(个数) = 2, n(和) = 4的组合。还是一样 我们需要回溯来解决。确定终止条件:当我们的path.size()==k且targetsum == sum说明我们找到了个数为k个且和为n的组合,这时候收获结果。单层递归逻辑:处理过程就是 path收集每次选取的元素,相当于树型结构里的边,sum来统计path里元素的总和。

2024-03-17 06:07:41 402

原创 代码随想录

然后还需要一个参数,为int型变量startIndex,这个参数用来记录本层递归的中,集合从哪里开始遍历(集合就是[1,...,n] )。单层递归的逻辑:一个for循环控制横向遍历,递归往深度搜索,for循环每次从startIndex开始遍历,然后用path保存取到的节点i。其实不定义这两个全局变量也是可以的,把这两个变量放进递归函数的参数里,但函数里参数太多影响可读性,所以我定义全局变量了。思路:使用回溯来解决,回溯跟递归一样 也是三部曲确定参数以及返回值,确定终止条件,单层递归逻辑。

2024-03-16 02:33:17 203 1

原创 代码随想录

思路:本题不要去构造线性二叉树而是去构造平衡bst。递归构造,终止条件为当我们的左区间大于右区间就return null,接下来定义根节点,根据数组中间值构造根节点。接下来就是构造左子树,我们要传入数组然后左区间和右区间。也是传入数组,然后传入左区间和右区间。思路:BST中序遍历是从小到大递增。那累加要从后往前累加,可以把中序遍历反过来也就是右中左。接着划分区间,root的左孩子接住下一层左区间的构造节点,右孩子接住下一层右区间构造的节点。, 中节点的处理逻辑就是让cur的数值加上前一个节点的数值。

2024-03-14 21:44:48 288 1

原创 代码随想录

思路:使用递归来删除节点,如果当前节点小于区间,那它的左孩子肯定都要删除,所以只需要看它的右孩子有没有在区间内的,也就是递归右子树,在上一层用父节点的左孩子来接住。如果当前节点大于区间那他的右孩子也都要删除,只需要看它的左孩子有没有符合区间的,也就是递归左子树,在上一层用右孩子来接住。思路:直接在叶子节点插入,如果遇到叶子节点我们就创建新的node然后返回,进入递归,根据元素的值确定搜索方向,比要插入的值比当前节点小 往左遍历,反之往右。最复杂的情况为第五种,我们要找到右子树的最左孩子。

2024-03-14 04:35:09 213 1

原创 代码随想录

那么我们来说一说,如果 root == q,或者 root == p,说明找到 q p ,则将其返回,这个返回值,后面在中节点的处理过程中会用到,那么中节点的处理逻辑,下面讲解。如果当前元素出现的频率大于最大频率:更新最大频率,再清空数组,再把当前元素的值放入数组。而且初始化的时候pre = NULL,这样当pre为NULL时候,我们就知道这是比较的第一个元素。弄一个指针指向前一个节点,这样每次cur(当前节点)才能和pre(前一个节点)作比较。思路:中序遍历树,放入数组。235.二叉树最近公共祖先。

2024-03-13 00:56:26 296

原创 代码随想录

因为是传入了两个树,那么就有两个树遍历的节点t1 和 t2,如果t1 == NULL 了,两个树合并就应该是 t2 了(如果t2也为NULL也无所谓,合并之后就是NULL)。题目中说了输入的数组大小一定是大于等于1的,所以我们不用考虑小于1的情况,那么当递归遍历的时候,如果传入的数组大小为1,说明遍历到了叶子节点了。那么应该定义一个新的节点,并把这个数组的数值赋给新的节点,然后返回这个节点。思路:如果要搜索的值比根节点大就向右搜索,反之向左 一直递归下去,只要找到就马上返回。直接构造t1的左子树和右子树。

2024-03-12 02:05:41 103

原创 代码随想录

思路:深度最大的叶子节点就是最后一行,最左边不一定是左节点。本题遍历顺序无所谓,只要保证有限向左搜索就行。本题还需要类里的两个全局变量,maxLen用来记录最大深度,result记录最大深度最左节点的数值。思路:本题使用后序遍历递归,要注意如何判断该节点是否是左叶子节点,要在父节点就进行判断如果该节点左孩子不为空,且左孩子的左节点为空,右节点也为空才是左叶子节点。思路:递归加回溯解决问题,target一路减。如果到叶子节点且target == 0 说明找到了一条路径 马上返回true。

2024-03-10 06:17:41 121 1

原创 代码随想录

思路:使用前序遍历递归+回溯来解决,遇到叶子节点终止处理逻辑。在本题,中的处理逻辑要放在叶子节点之前。向左递归然后回溯,向右递归然后回溯。思路:本题使用后序遍历递归来判断,求出左子树的高度和右子树的高度,两个做差的绝对值如果大于1 就 直接返回-1.257 二叉树的所有路径。

2024-03-09 07:18:37 177

原创 代码随想录

思路:用普通二叉树的思想去做题,后序遍历递归。中处理左子树的值加上右子树的值+1。思路:使用后序遍历递归的方法,遇到空结点返回0.思路:N叉树题目都是孩子节点,所以要遍历去递归。完全二叉树的节点个数。

2024-03-07 23:51:37 211

原创 代码随想录

思路:使用队列来作题,再定义一个size用来记录下一层要弹出几个元素。每弹出一个元素就把他的孩子再放入队列中。思路:本题要注意翻转的是指针而不是值。前序遍历或后序都可以 使用swap库函数。

2024-03-07 02:38:24 192

原创 代码随想录

前序遍历中左右,中序遍历左中右,后序遍历左右中。中在哪里,哪里就是处理逻辑。

2024-03-05 22:18:12 69 1

原创 代码随想录

思路:先用map存放元素和其出现的元素。再放入小顶堆也就是自定义优先级队列。把元素放入小顶堆,且只放k个。思路:使用自定义单调队列来做题。但要注意是双向队列这样两端都可以进出。239.滑动窗口最大值。347.前K个高频元素。

2024-03-04 23:47:57 201 1

原创 代码随想录

思路:也是用栈来完成,遇到数字入栈,记得转成int型,遇到操作符我们从栈内取出2个元素做操作再把结果入栈。最后的答案就在栈的最后一个元素。思路:用栈来实现,当栈非空或我们当前遍历元素与栈顶元素不一样时入栈,否则出栈。1047.删除字符串所有项链元素。150.逆波兰表达式。

2024-03-02 23:57:31 129

原创 代码随想录

我们遇到一个左括号 就把对应的右括号放入栈。当字符串遍历到右括号,我们就看看栈顶元素跟当前遍历的元素匹不匹配。栈为空说明全部匹配。思路:用一个队列就行,当栈要弹出元素时,只需要让队列循环弹出元素再加入队列直到最后一位元素位于队列出口,此时该元素就是栈顶元素。思路:使用两个栈来模拟队列。232.用栈实现队列。225.用队列实现栈。

2024-03-02 00:30:01 197

原创 代码随想录第七天

思路:定义一个新的字符串把两个字符串拼接起来赋值给它。然后在新字符串中找子串。思路:本题采用kmp算法。首先获取next数组,再根据next数组在文本串中去找子串。思路: 整体反转再分段反转。459.重复的子字符串。

2024-03-01 01:29:10 186

原创 代码随想录第六天

思路:双指针思路,先统计字符串数字个数。然后对字符串进行扩容。定义两个指针,一个指向扩容后的末尾,一个指向旧字符串的末尾。遇到非数字就加入到扩容后的末尾。否则指针不断从后向前赋值number 注意 number也是反着赋值的。最后两个指针同时减减。思路:循环i可以2k去遍历。然后处理边界问题上,一般的编程语言都是左闭右开,所以 reverse(i,i+k)是不包含i+k的。思路:使用双指针方法来遍历字符串。一个在头,一个在尾部。541.反转字符串2。

2024-02-29 00:28:38 163

原创 代码随想录第五天

接下来如何移动left 和right呢, 如果nums[i] + nums[left] + nums[right] > 0 就说明 此时三数之和大了,因为数组是排序后了,所以right下标就应该向左移动,这样才能让三数之和小一些。思路:使用unordered_map来存放A+B的值以及出现的次数,本题无需去重。如果 nums[i] + nums[left] + nums[right] < 0 说明 此时 三数之和小了,left 就向右移动,才能让三数之和大一些,直到left与right相遇为止。

2024-02-28 02:34:21 264 1

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除