自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 算法训练一刷总结

但是感觉理解的不深入,对于动态规划也迟迟没有动手。这次感觉还是没到题目要深刻理解,多做总结。定期可以看一下这一轮的博客,并且重新写一下题目,如果有新的思考再完善博客的细节,否则容易遗忘。看完算法题题解之后,还是要自己用代码实现一下题目,否则会错过很多细节。学会总结模版对应同样类型的题目,比如动归模版,二叉树模版。以前陆陆续续其实也刷过题目。

2024-01-08 19:21:29 396

原创 算法训练day60|单调栈part0

如果数组本身就是升序的,例如[2,4,6,8],那么入栈之后 都是单调递减,一直都没有走 情况三 计算结果的哪一步,所以最后输出的就是0了。本题是要找每个柱子左右两边第一个小于该柱子的柱子,所以从栈头(元素从栈头弹出)到栈底的顺序应该是从大到小的顺序。对5来说,(left,right)范围内(不包括left,right)都是比5高的柱,所以对5的体积可以是5。,在 8 入栈后,6 开始与8 进行比较,此时我们得到 mid(8),rigt(6),但是得不到 left。,而不是左边第一个小于该柱子的高度。

2024-01-06 11:11:30 1786

原创 代码训练day59|单调栈part02

此时的栈顶元素st.top(),就是凹槽的左边位置,下标为st.top(),对应的高度为height[st.top()](就是图中的高度2)。取栈顶元素,将栈顶元素弹出,这个就是凹槽的底部,也就是中间位置,下标记为mid,对应的高度为height[mid](就是图中的高度1)。当前遍历的元素i,就是凹槽右边的位置,下标为i,对应的高度为height[i](就是图中的高度3)。栈头元素就是凹槽底部的柱子,栈头第二个元素就是凹槽左边的柱子,而添加的元素就是凹槽右边的柱子。第二次遍历数组并不会覆盖之前的结果;

2024-01-05 17:10:31 943

原创 day58算法训练|单调栈part01

时间复杂度为O(n)。,因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高的元素,优点是整个数组只需要遍历一次。,因为我们遍历数组的时候,我们不知道之前都遍历了哪些元素,以至于遍历一个元素找不到是不是之前遍历过一个更小的,所以我们需要用一个容器(这里用单调栈)来记录我们遍历过的元素。在使用单调栈的时候首先要明确如下几点:1. 单调栈里存放的元素是什么?单调栈里只需要存放元素的下标i就可以了,如果需要使用对应的元素,直接T[i]就可以获取。

2024-01-04 12:38:13 442

原创 day 57 算法训练|动态规划part17

1. dp数组(dp table)以及下标的含义是不是能找到一种递归关系,也就是判断一个子字符串(字符串的下表范围[i,j])是否回文,依赖于,子字符串(下表范围[i + 1, j - 1])) 是否是回文布尔类型的dp[i][j]:表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串,如果是dp[i][j]为true,否则为false。dp数组无法直接得出回文数量,但是可以判断是否为回文,如果是,直接增加即可2. 递推公式整体上是两种,就是s[i]与s[j]相等,s[i]与s[j]不相等这两种。

2024-01-03 18:36:05 459

原创 算法训练day56|动态规划part16

当 同时删word1[i - 1]和word2[j - 1],dp[i][j-1] 本来就不考虑 word2[j - 1]了,那么我在删 word1[i - 1],是不是就达到两个元素都删除的效果,即 dp[i][j-1] + 1。当word1[i - 1] 与 word2[j - 1]相同的时候,dp[i][j] = dp[i - 1][j - 1];

2024-01-02 02:27:14 866

原创 day55 算法训练|动态规划part15

从递推公式dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];从递推公式dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];例如: s:bagg 和 t:bag ,s[3] 和 t[2]是相同的,但是字符串s也可以不用s[3]来匹配,即用s[0]s[1]s[2]组成的bag。dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j]。当然也可以用s[3]来匹配,即:s[0]s[1]s[3]组成的bag。

2024-01-01 19:06:06 1142

原创 算法训练day53|动态规划part14

那就看看text1[0, i - 2]与text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]与text2[0, j - 2]的最长公共子序列,取最大的。如果text1[i - 1] 与 text2[j - 1]相同,那么找到了一个公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1;主要就是两大情况: text1[i - 1] 与 text2[j - 1]相同,text1[i - 1] 与 text2[j - 1]不相同。相当于就是1143题。

2023-12-31 00:08:31 409

原创 day52 算法训练|动态规划part13

与上一题区别由于要求连续的,所以就只要比较nums[i]与nums[i - 1],而不用去比较nums[j]与nums[i] (j是在0到i之间遍历)。dp[i][j] :以下标i - 1为结尾的A,和以下标j - 1为结尾的B,最长重复子数组长度为dp[i][j]。所以:if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);A[i - 1] 和B[j - 1]相等的时候,dp[i][j] = dp[i - 1][j - 1] + 1;

2023-12-30 22:28:58 886 2

原创 算法训练day51|动态规划part12

如果i为1,第1天买入股票,那么递归公式中需要计算 dp[i - 1][1] - prices[i] ,即 dp[0][1] - prices[1],那么大家感受一下。那么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。即:dp[i][2] = dp[i - 1][0] + prices[i];

2023-12-30 17:12:36 919

原创 算法训练day50|动态规划part11

第0天第二次买入操作,第二次买入依赖于第一次卖出的状态,其实相当于第0天第一次买入了,第一次卖出了,然后再买入一次(第二次买入),那么现在手头上没有现金,只要买入,现金就做相应的减少。dp[i][j]中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金。第0天做第一次卖出的操作,可以理解当天买入,当天卖出,所以dp[0][2] = 0;第0天做第一次买入的操作,dp[0][1] = -prices[0];第0天没有操作,即:dp[0][0] = 0;

2023-12-27 10:31:25 785

原创 算法训练day49|动态规划part10

和 dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);那么dp[0][0]表示第0天持有股票,此时的持有股票就一定是买入股票了,因为不可能有前一天推出来,所以dp[0][0] -= prices[0];同样dp[i][1]取最大的,dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);由于只需要用到dp[i-1][0],dp[i-1][1]来推导dp[i][0],dp[i][1]

2023-12-26 09:10:56 1078 1

原创 day48算法训练|动态规划part09

如果偷第i房间,那么dp[i] = dp[i - 2] + nums[i] ,即:第i-1房一定是不考虑的,找出 下标i-2(包括i-2)以内的房屋,最多可以偷窃的金额为dp[i-2] 加上第i房间偷到的钱。,那么左右孩子就可以偷,至于到底偷不偷一定是选一个最大的,所以:val2 = max(left[0], left[1]) + max(right[0], right[1]);然后dp[i]取最大值,即dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);

2023-12-25 11:34:23 1086

原创 day46算法训练|动态规划part8

代码随想录。

2023-12-23 14:25:51 386

原创 day45 算法训练|动态规划 part07

其他位置由于是求最小值,需要初始化为一个最大的数(至少比result可能的最大值要大),否则就会影响递推公式的更新(实际最小值比初始化的值要大的时候:min(dp[j - coins[i]] + 1, 初始值)=初始值)虽然先背包循环,再物品循环,会影响到dp[j] 与dp[i][j]的互相对应关系,但是不影响最终结果,只要把整个过程遍历完了,仍然能够得到最小值。dp[i][j]: coins[0..i]的选择中达到jamount用的coins的最少个数。dp[i-1][j]:不选择第i个硬币。

2023-12-22 13:34:28 374

原创 day44代码训练|动态规划part06

完全背包和01背包问题唯一不同的地方就是,每种物品有无限件。1. dp数组的含义dp[i][j] 0-i物品,重量为j的容量时,最大的价值2. 递推公式dp[i][j] = max(dp[i-1][j],dp[i][j-weight[i]]+value[i]);两种状态,不用物品i的话,直接是用dp[i-1][j]选用物品的话,为了重复使用物品i,其实是dp[i][j-weight[i]]+value[i],因为对dp[i][...]都是仍有机会再次使用物品i得3.初始化dp[...][0]=0 由于重量为

2023-12-21 21:43:56 961

原创 day43 动态规划part05

与昨天的分割等和子集其实是同样的题分为两堆后,要求差值最小,其实就是分堆最大,并且范围是[0,sum/2]

2023-12-20 18:10:10 864

原创 day42代码训练|动态规划part04

首先从dp[i][j]的定义出发,如果背包容量j为0的话,即dp[i][0],无论是选取哪些物品,背包价值总和一定为0。j < weight[0]的时候,dp[0][j] 应该是 0,因为背包容量比编号0的物品重量还小。当j >= weight[0]时,dp[0][j] 应该是value[0],因为背包容量放足够放编号0物品。4. 确定遍历顺序按照递推公式可得:需要用表格上方和左上方的数据,所以只要从后往前遍历,先递归物品/先递归背包重量都是可以的先递归物品更好理解。

2023-12-19 16:06:46 951

原创 day41算法训练|动态规划part03343. 整数拆分

确定遍历顺序,先来看看递归公式:dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));可见当dp[n] (n>=4)时,dp[n] == integerBreak(n)因为dp作为被拆分项,他的Best是对其接着拆分。dp[i] 是依靠 dp[i - j]的状态,所以遍历i一定是从前向后遍历,先有dp[i - j]再有dp[i]。首先一定是遍历节点数,从递归公式:dp[i] += dp[j - 1] * dp[i - j]可以看出,

2023-12-18 14:05:51 861

原创 day39算法训练|动态规划part02

这里要看一下递推公式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],因为dp[i][j]只有这两个方向过来。这样就可以保证推导dp[i][j]的时候,dp[i - 1][j] 和 dp[i][j - 1]一定是有数值的。dp[i][j] :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径。

2023-12-16 17:22:24 955

原创 day38 代码训练|动态规划01

理论基础做之前把状态转移在dp数组上模拟一遍。

2023-12-15 16:52:43 384

原创 算法训练day37|贪心算法part06

遇到了strNum[i - 1] > strNum[i],让strNum[i - 1]--,然后strNum[i]及以后给为9。根据这种情况从后往前遍历。没有固定套路,更多是记忆。

2023-12-15 14:06:18 383

原创 day36算法训练|贪心part05

就是需要移除的区间个数了。

2023-12-15 13:21:57 364

原创 day35 算法训练|贪心算法 part04

如果两个气球重叠,我们可以更新两个气球的右边界为两个右边界的最小值,故两个右边界的最小值之前一定需要一支弓箭。如果下一个气球,与前两个气球的重叠处还重叠(start3<min(end1,end2)),则三个气球重叠,不需要多一个箭来射破气球。先确定h顺序,再确定k,我们有了h的先后顺序,我们可以保证,在当前之前安排好的身高都比当前身高高,再就只用考虑到k的顺序了。有两个维度需要同时考虑的时候先考虑其中之一,再考虑另一个。如果先确定k,不仅k没有排好,h也没有排好,并不合适。局部最优:让气球尽可能的重叠。

2023-12-14 21:23:43 558

原创 day34算法训练|贪心算法

区间和1 + 区间和2 < 0 同时 区间和2>0,只能说明区间和1 < 0, 那么就会从假设的箭头初就开始从新选择其实位置了。第二次全部判断右边的关系(此时需要从后往前遍历,因为 rating[5]与rating[4]的比较 要利用上 rating[5]与rating[6]的比较结果)如果 curSum<0 说明 区间和1 + 区间和2 < 0, 那么 假设从上图中的位置开始计数curSum不会小于0的话,就是 区间和2>0。当发生这种情况说明,肯定是直接返回-1了,不需要考虑溢出问题:来源视频评论区。

2023-12-14 16:47:12 430

原创 算法训练day32|贪心算法part02

局部最优:记录每天的利润,只需要累加利润为正的天数每次移动取最大跳跃步数(得到最大的覆盖范围),每移动一个单位,就更新最大覆盖范围。贪心算法局部最优解:每次取最大跳跃步数(取最大覆盖范围),整体最优解:最后得到整体最大覆盖范围,看是否能到终点。贪心的思路,局部最优:当前可移动距离尽可能多走,如果还没到终点,步数再加一。整体最优:一步尽可能多走,从而达到最少步数。如果当前范围内不够到达终点,需要多跳一步,开启下一个范围nums.length==1为特殊情况需要单独讨论

2023-12-14 09:55:45 722

原创 算法训练day31|贪心算法part1

理论基础:贪心算法没有模版通过找到局部最优解来获得全剧最优解。

2023-12-13 23:29:59 1125

原创 算法训练day30|回溯part06

【代码】算法训练day30|回溯part06。

2023-12-11 13:14:20 397

原创 算法训练day29|回溯算法part5 补卡

通过nums[i]==nums[i-1]&&used[i-1]=true时才能继续for循环,否则continue,这样就确定三个1的顺序一定是1a,1b,1c 在这三个1内没有排序的可能,否则可能会有六种排序方式。没法排序去重的问题,就需要一个set来记录同一父节点下的同层上使用过的元素(使用过的就不能在使用了)也可以理解为,有重复多个数字,只让这些数字直接有一种顺序比如有三个1:1a,1b,1c。本题涉及到排列的去重,去重的题,如果可以的话,先对题目进行排序,方便我们去重。

2023-12-11 12:52:08 350

原创 day 28|回溯算法 part04

可以不写终止条件:1.因为所有节点都要遍历2.startIndex是不断在增大的,会不满足for循环条件,相当于直接return,所以不会进入死循环;最后遍历所有节点,就相当于记录下了所有的子集集合(不需要剪枝)如果为4,可以直接结束,进行剪枝,如果为4个ip段时还回溯搜索完了整个字符串,说明可以把当前path加入结果。保存结果的条件要放在逻辑最开头 (相当于是多叉树的前序遍历位置)空集也相当于遍历到了(多叉树根节点)如果要写终止条件,收获结果应该要写在终止条件前面,否则会漏掉自己。这样写更好(工程习惯)

2023-12-10 21:57:36 336

原创 算法训练 day27|回溯算法part03

本题去重是去去除同一树层的重复选取,如[1,2(1),2 (2),2(3),4,5]中和为11的子集有[2,4,5] [2(第二个2),4,5]重复属于第二类重复。startIndex就可以作为切割线:是下一个子串开始的位置,所以当startIndex==s.length()时,就时结束的条件达成的时候。第一类重复时子集[2(1),2 (2),2(3)]相当于是用了三个不同的2,是树枝上的重复。而 used[i - 1] == true,说明是进入下一层递归,去下一个数,所以是树枝上。

2023-12-05 16:23:36 874

原创 算法训练day25|回溯算法part2

结束条件: index == digits.size() <->因为到digits最后一位时,最后一位还要做处理,所以其实是当全部遍历结束的时候( index == digits.size())直接保存结果。本题时多个集合中的组合,不需要startIndex来控制单个集合组合重复/顺序,但是需要index来遍历输入的字符串。,当digits为“”的时候返回值,有case举例,所以需要单独处理此类特殊情况。注意:sum和长度不应该在一个if里面同时判断,长度是用来判断结束条件的,避免冗余的复杂度。

2023-12-02 13:02:58 378

原创 代码训练day24|回溯part1

回溯本质是穷举,有的题目,高效的穷举已经是最有效的办法了排列对比于组合前调顺序回溯可以抽象为一种树形结构(N叉树)回溯算法中函数返回值一般为void。再来看一下参数,因为回溯算法需要的参数可不像二叉树递归的时候那么容易一次性确定下来,所以。什么时候达到了终止条件,树中就可以看出,一般来说搜到叶子节点了,也就找到了满足条件的一条答案,把这个答案存放起来,并结束本层递归。回溯法一般是在集合中递归搜索,集合的大小构成了树的宽度,递归的深度构成的树的深度。有选择,选择后需要回溯,撤销处理结果。

2023-12-01 12:15:16 937 1

原创 算法训练day23|二叉树 part9

3. 遇到比范围小的根节点,删除该节点和其左子树(左子树比根节点小),返回右子树。但是右子树中可能还存在不符合范围的值,所以应该返回右子树的遍历函数(遍历整颗树)5.遇到在范围内的根节点,不需要操作,直接按照整数遍历走就可以了。1.删除节点可以靠返回值来操作,返回其子节点就是删除了该节点。所以返回值选择为节点,要处理空节点,否则正常范围内返回根节点。递归:中序,清空结果集的技巧,遍历一遍便可求众数集合。有序数组倒叙->中序遍历反过来右中左。通过递归函数的返回值来增删二叉树。4. 遇到比范围大的根节点同理。

2023-11-30 13:18:35 375

原创 代码训练day22|二叉树part08

不好判断p,q大小,可以先判断两种其他情况(root<p&&root<q和root>p&&root>q),之后剩下的情况就是root的val在p和q之间。二叉搜索树插入,因为BST已经有序,所以肯定不用遍历整颗树,只需要遍历边即可。返回值不为空的时候立即返回,不需要后续的逻辑处理,所以只是搜索一条边。反证法:如果不是最近,向左/右向下遍历,都会错过p,q中的某一个。1. 当root的val在p与q之间时,root为最近公共祖先。迭代法,需要双指针来记录父节点(parent),需要记录根节点,作为返回值。

2023-11-29 13:26:07 345 1

原创 算法训练day21|二叉树part07

上图第三点:返回的是pq第一次出现的节点,传上去为了找到最近公共祖先(该节点左右皆为非空)此种情况为情况一(最近公共祖先不是pq节点本身)。但是情况1已经包含了情况2(pq为最近公共祖先)遇到p,q就直接返回,然后一直通过途中第三点的情况(公共祖先那边非空,另一边为空,所以上传公共祖先这边的返回值)上传到根节点,返回为最终结果。2. count>max的更新需要在count==max添加结果之后,或者独立出来(if+else if)否则先让max=count,再去判断如果想等就加入,会有冗余的结果。

2023-11-28 13:24:23 359 1

原创 代码训练day18|二叉树part6

同步遍历,如果只有一个树有该节点,直接返回有该节点的子数,(不需要一个个遍历该子数),相当于只用遍历两颗二叉树共同拥有的部分。中左右遍历顺序都可以,因为,相当于在遍历其中一个二叉树,并且修改那个二叉树。迭代法十分简单,不需要遍历所有节点,按照二叉搜索树性质遍历即可。不止比较根节点和子节点,是根节点与子树所有节点的关系。long来避免二叉树的值是int_Min_Value。方法一:用双指针中序遍历来判断是不是递增的。方法二:用子树的大小范围来验证。分割数组的区间定义一定要相同。构造二叉树一定要用前序遍历。

2023-11-27 14:18:39 346 1

原创 算法训练day18|二叉树part05

思路:用前序遍历(因为先遍历左边),并且遍历的时候记录节点的深度。由于先遍历左节点,所以最后得到的值就是树的最后一行最左边的值。减少赋值的次数:只在叶子节点,并且最大深度更新的时候赋值。由于优先遍历左节点,所以最大深度更新的时候就是最左侧的节点。没有中的逻辑,所以前中后序都一样,(其实前序位置更改变量,后续位置做回溯)113题中不要跟112的类型搞混,113需要遍历整个二叉树,不能提前返回。写代码的时候可以把分割的数组打印出来,更好debug。5.依据中序切割切割后序数组,切成后序左,和后序右。

2023-11-25 12:46:36 342

原创 算法训练day17|

写代码时错误的点:路径加入结果的条件是叶子结点,并不是递归返回的时候。思路:需要知道左节点是否为叶子节点之后在往结果上加,所以需要后序遍历。思路:利用求高度后序遍历,在后续位置得到高度的同时顺便在每个节点判断平衡性,用全局变量来储存结果。2.比起用全局变量储存结果更好的是,用返回值(-1,高度不可能是-1,所以-1可以代表不平衡)回溯一定伴随着递归一一对应(同时进行的,比如递归在if的括号中,那么括号中一定要有对应的回溯)思路:需要路径,所以是进入节点的信息,逻辑处理应该放在前序遍历。

2023-11-24 12:04:39 341 1

原创 算法训练 day16|二叉树深度,高度,节点个数

分为一个满二叉树和另一个来计算完全二叉树计算,最后相当于是拆成了各个满二叉树(利用完全二叉树特性,没有遍历所有节点)求高度用后序遍历,求深度用前序遍历。最大深度等同于高度所以用后序遍历。222.完全二叉树的节点个数(优先掌握递归)104.二叉树的最大深度 (优先掌握递归)111.二叉树的最小深度 (优先掌握递归)前序求深度,需要参数中有深度,随着递归改变。可以用后序遍历,只是要增加条件。思路:后序遍历算最大深度。*** 其实是求高度;

2023-11-23 10:12:00 77

空空如也

空空如也

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

TA关注的人

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