- 博客(53)
- 收藏
- 关注
原创 代码随想录算法训练营Day60 | 84. 柱状图中最大的矩形
因为在接雨水中,如果不能够形成一个完整的谷,那么就不需要进行任何计算,也就是说单调递增、递减的数组本来就不该有任何计算结果。这个要求的变化加大了双指针的难度,所以优先讨论更加适用的单调栈解法。和上一题一样按行来计算矩形面积,对于固定的一列,需要这一列的高度、对应的左边界、对应的右边界。和接雨水一样,本题同样有双指针 + dp 的解法,但是这个解法的时间复杂度有些可疑。和接雨水相比,本题中的双指针 + dp 会更加复杂一些,因为要求的不再是。,dp 的递推变得很困难,我也不确定具体的复杂度。
2023-09-16 14:03:30
312
原创 代码随想录算法训练营Day59 | 503. 下一个更大元素II | 42. 接雨水
一方面,单调栈适用于寻找当前元素左侧/右侧的第一个更大元素值,和本题的“寻找谷地”有紧密的联系;另一方面,之前在思路中提到的是寻找“左侧/右侧的最大高度”,而不是第一个更大元素,这似乎又没有很紧密的关系。计算,就需要找到这一行(一个谷内的行,不是传统意义上的一行)的起始位置。暴力解法中有大量的重复计算:在计算每一列作为谷底的时候,都要进行一次遍历来得到左侧的最大高度和右侧的最大高度。其中高需要列的值,宽需要列的下标,既然通过下标可以直接获取值,栈内只需要记录下标即可。实际的记录过程有点类似于简单的 dp。
2023-09-16 13:54:52
345
原创 代码随想录算法训练营Day58 | 单调栈 | 739. 每日温度 | 496. 下一个更大元素 I
在遍历到当前元素的时候,需要把当前元素和栈口的元素进行比较,从而得到当前元素的某些性质。由于只能比较当前元素和栈口元素,所以对栈内的元素性质有要求:(从 stack top 到 stack bottom)单调增或者单调减。单调栈的意义是帮助我们存放已经遍历过的元素,从而能够比较当前元素和之前遍历过的元素(其实只能和栈口的元素比较,所以需要栈内保持。单调栈的本质是空间换时间,用一个栈来记录遍历过的元素,但只需要遍历一边即可。注意,答案中比较的是元素的值,但是栈中维护的只是下标,使用的时候不要搞混。
2023-09-10 15:02:37
349
原创 代码随想录算法训练营Day56 | 583. 两个字符串的删除操作 | 72. 编辑距离 | 编辑距离总结篇
编辑距离总结在之前的讲解中,或多或少提到了编辑距离。那些题目或多或少都有一些别的解法,或者看作是重复字数组、重复子序列的变种。但是,实际上他们都能被看作是编辑距离判断子序列可以看作:只允许删除t的元素的情况下能否得到s不同的子序列可以看作:有多少种删除t的元素的方法能够得到s两个字符串的删除操作可以看作:允许删除两个字符串的元素,使其相同所需要的最少操作数编辑距离就是真正的编辑距离。
2023-09-09 13:03:35
383
原创 代码随想录算法训练营Day55 | 392. 判断子序列 | 115. 不同的子序列
但实际上,这是一道特殊版本的最长公共子序列,同时也是编辑距离的入门。看到多少种方法 + 子序列,第一反应是回溯所有的子序列,然而数据量很明显不可能支持回溯,题目难度也没有到必须暴力搜索的地步。题目要求判断 s 是否是 t 的子序列,其实相当于要求 s 和 t 的最大公共子序列的长度就是。dp 数组的初始化:对于当前的定义,初始化和之前是一样的,都是针对第一行和第一列进行单独的初始化。dp 数组的初始化:根据递推公式的要求,还是要初始化第一行和第一列。的递推公式进行了很长的讨论。的含义是反的,但不影响解题。
2023-09-09 05:22:41
331
原创 代码随想录算法训练营Day53 | 1143. 最长公共子序列 | 1035. 不相交的线 | 53. 最大子序和 (动态规划)
经过上述抽象化,可以发现,本题说是求绘制的最大连线数,其实就是求两个字符串的最长公共子序列的长度!来自代码随想录:直线不能相交,这就是说明在字符串 A 中找到一个与字符串 B 相同的子序列,且这个子序列不能改变相对顺序:只要相对顺序不改变,链接相同数字的直线就不会相交。虽然是一道一维的子序列,但还是很好体现了 dp 利用当前元素递推子问题的特性。的比较来得到正确的递推公式(dp 数组的定义还是比较好想的)。注意,由于这里的 dp 数组定义发生了变化,最终的结果一定是。,这样就可以直接使用之前的。
2023-09-08 14:58:58
245
原创 代码随想录算法训练营Day52 | 300. 最长递增子序列 | 674. 最长连续递增序列 | 718. 最长重复子数组
作为 dp 的序列第一题,难度不高,最大的难点在于找到正确的 dp 数组定义。一些思路的小提示:之前两题的定义都是需要以当前元素结尾的最大子序列长度,而本题有两个输入数组,所以使用二维数组来定义 dp 似乎也很合理。由于需要保持之前的状态,滚动数组的解需要内层遍历从后向前进行。本题问的是子序列,定义为“由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序”。dp 的遍历顺序:从小到大即可,由于只需要左上角的元素进行过初始化,两层循环的嵌套也就无所谓内外顺序。的最长重复子序列的长度。
2023-09-04 15:09:17
194
原创 代码随想录算法训练营Day51 | 309. 最佳买卖股票时机含冷冻期 | 714. 买卖股票的最佳时机含手续费 | 股票总结
股票问题总结股票问题是第一次在 dp 中需要记录状态的题型。之前的 dp 题,无论是打家劫舍还是背包问题,都是考验对子问题最优解的利用,即正确的递推公式+遍历顺序。股票问题则需要对子问题进行分类讨论,记录各个状态下的子问题最优解,这一点是非常新颖的。同时,不知道是不是巧合,大部分股票问题都可以用贪心来解决,虽然实现贪心的难度不小。最标准的股票问题应该是122. 买卖股票的最佳时机II,需要真正地记录并利用状态。随后,复杂的限制交易次数的股票问题188.买卖股票的最佳时机IV。
2023-09-03 14:00:41
319
原创 代码随想录算法训练营Day50 | 123. 买卖股票的最佳时机III | 188. 买卖股票的最佳时机IV
本题比之前两题难很多,之前的题目确定了“买卖一次”或者“无限买卖”,而本题规定的是“最多买卖两次”,也就是说可以买卖一次、买卖两次、完全不进行买卖,显得非常复杂。,因为如果进行一次买卖就能获得最大净利润,那么总可以在最后一天进行一次(无意义)的买入+卖出。的四个值中取最大值。在之前的题中,已经解释过,想要受益最大,最后一天必然需要将股票卖出。本题总让我觉得跟多重背包有点类似,就是在原题的基础上进行了升维处理,但是题目的含义没有改变。的三维数组,但本质上是一样的,无非就是在内部遍历时多加了一个遍历。
2023-09-01 12:49:06
189
原创 代码随想录算法训练营Day49 | 121. 买卖股票的最佳时机 | 122. 买卖股票的最佳时机II
的:当前能否卖出股票取决于之前是否持有股票,只记录之前得到的最大收益就无从得知对于股票的持有状态。dp 数组的初始化:从递推公式可知,我们需要初始化第一天的 dp 数组,其余值设为 0 即可(可以处理股票价格一直下跌的状态)本题的条件和上一唯一的不同在于股票可以多次买卖了(但是同时只能持有一支股票),其余条件都一样,甚至于本题也有一种贪心解法。本题只能买卖一次股票,也就是找最大的前后差:找到左边最小的,找到右边最大的,得到的最大非负差值就是最大利润。的滚动数组即可,依靠天数 i 对 2 的取余即可。
2023-09-01 12:08:58
251
原创 代码随想录算法训练营Day48 | 198. 打家劫舍 | 213. 打家劫舍II | 337. 打家劫舍III
很明显,暴力递归对子问题的重复计算导致了超时,所以我们希望使用 dp 来记录已经得到的子问题的最优解,不断递归来得到全局的最优解。和上一题的区别在于首尾元素也是相邻的,所以按照上一题的逻辑推到最后一栋房屋时,实际上不能自由根据收益选择是否要抢,还依赖于第一栋房屋的状态。但是递归超高的时间复杂度,导致超时,因为递归中有大量的重复计算。对于 dp 来说,二叉树的递归性质反而决定了题目更简单,因为递归只允许返回当前节点的状态。同样,其实也不需要保存每一个访问过的房屋的状态,直接记录最佳解即可。
2023-08-30 16:31:55
412
原创 代码随想录算法训练营Day46 | 139.单词拆分 | 多重背包 | 背包问题总结
理论基础通过之前这一堆背包问题的练习,解决背包问题已经比较有套路了,对遍历顺序、初始化的理解也算不错。然而,将复杂的问题背景抽象成背包问题,仍然是需要经过思考的,其中最后一块石头的重量 II、目标和绝对是这种复杂抽象的难题。另外,很多背包问题看上去也都能用回溯算法解决,但毫无疑问都一定会超时。区别在于,背包问题依然能够依靠子问题的解来节省复杂度,而回溯算法不可避免地需要进行穷举,只不过是优雅的穷举,两者还是有本质上的区别。代码随想录上总结了不同的递推公式。
2023-08-30 11:11:57
270
原创 代码随想录算法训练营Day45 | 70. 爬楼梯 (进阶) | 322. 零钱兑换 | 279. 完全平方数
看作是物品,n 看作是背包容量的话,就又是一道标准的完全背包问题:求填满背包使用的最少物品数。本题中的物品就是可以行走的步数 [1, 2],重量是 n,可以重复选取步数,求走到第 n 层有多少种走法。如上所述,本题只要求满足金额的硬币数,不在意满足金额的结果的顺序,所以物品、背包的遍历顺序都可以。本题看上去是个简单的爬楼梯,但实际上是个简单的完全背包,重要的是可以考验对物品和背包的遍历顺序的理解。dp 的遍历顺序:由于不需要排列,二维数组可以解决,物品和背包的顺序无所谓。以完全背包的思路来解题,正如。
2023-08-29 14:15:28
519
原创 代码随想录算法训练营Day44 | 完全背包 | 518. 零钱兑换 II | 377. 组合总和 Ⅳ | 完全背包小总结
在求装满背包有几种方案的时候,认清遍历顺序是非常关键的;在先物品后背包时,当进行物品 i 对背包容量的更新时,物品 i+1 肯定不会出现在当前的结果中,也就是说在得到的结果中,物品 i+1 一定会出现在物品 i 的后面,顺序被固定了。e.g. 只会出现,绝不会出现在先背包后物品时,会在大小为 j 的背包内选取所有物品的可行结果,然后对大小为 j+1 的背包进行选取,所以物品出现的顺序是不固定的。e.g. 可能会出现和。
2023-08-28 13:32:50
331
原创 代码随想录算法训练营Day43 | 1049. 最后一块石头的重量 II | 494. 目标和* | 474. 一和零
题目链接理论基础题目描述比较复杂,但还是可以抽象化成 01 背包的变种:由于重量不相等的石头碰撞后还会留下差值的石头,所以只要将所有的石头分成两组,并希望两组石头的总重量之差接近 0 即可。抽象后的题意:给定石头stones,从中选出一部分石头,其总重量尽可能接近所有石头的总重量的一半。此时这就是 01 背包的一个变种:尽可能填满背包。分割总和子集:能不能装满背包最后一块石头II:尽可能装满背包目标和:装满背包有多少种方法一和零:尽力装满背包有多少物品。
2023-08-28 06:37:15
229
原创 代码随想录算法训练营Day41 | 343. 整数拆分 | 96. 不同的二叉搜索树
由于 BST 的性质,对于 i+1 来说,可以从 [1, i] 中任取 [1, k] 组成 BST,然后将 i+1 作为这个 BST 的最右叶子节点,然后将 [k+1, i] 组成的 BST 作为 i+1 的左子节点。但实际上,题目给的例子已经很好地展示了这个关系。最直观的想法是,对于 [1, i] 的数字组成的 BST,i+1 总是能成为这个 BST 的最右叶子节点和根节点的(右侧)父节点。的情况还有一种,3 是 1 的右子节点,2 是 3 的左子节点,这个似乎是个例外,所以之前的关系还需要再拓展。
2023-08-24 14:14:55
94
原创 代码随想录算法训练营Day42 | 01背包理论基础 | 01背包 (滚动数组) | 416. 分割等和子集
以上总结了两种01背包的解法:二维数组在清楚定义的情况下,更为简单明了,收到的限制也更少,但空间复杂度较高;一维滚动数组思路巧妙,需要特定的遍历顺序(内外层、倒序),但有超低的空间复杂度,代码简洁。其中的难点(思维点)在于不同维度的遍历顺序同一纬度的前后遍历顺序不同的递推公式初始化逻辑只有明白不同方法中以上难点的回答,才能真正理解01背包!
2023-08-24 09:36:53
183
原创 代码随想录算法训练营Day39 | 62. 不同路径 | 63. 不同路径 II
另外,图论中的深度搜索似乎也可以完成:将路径看成二叉树的话,遍历所有的叶子节点即可。要注意,计算组合的时候不能直接计算分子、分母然后相除,而是要在计算分子时不断除以分母,防止溢出。,所以会直接超时,因为其中绝大部分的遍历都是没有意义的。本题的初始化中,“障碍之后的位置无法到达”也是个坑。步是向下走的,所以所有路径的总数是。本题可以用数论直接分析出结果:对于。
2023-08-23 04:19:18
159
原创 代码随想录算法训练营Day38 | 理论基础 | 509. 斐波那契数 | 70. 爬楼梯 | 746. 使用最小花费爬楼梯
另外,本题一个变种就是如果每一步能够爬 m 阶(本题 m=2),那么有多少种解法。区别只是在每一层内部加一个 for loop 循环。本题是非常基础的 dp,主要是熟悉 dp 五部曲的方法论。作为基础的 dp,维护整个 dp 数组有些昂贵了,只需要维护前两个值即可。可以理解为离开第 i 层(向上爬 1 或 2 阶)所需要的代价。那这就是一个考察点了,对。一定要初始化为1,此时可能候选人就要强行给。本题的题目描述有些令人费解。,使用动态规划是最有效的。,就可以发难了:为什么。的定义理解的不深入。
2023-08-23 03:45:53
215
原创 代码随想录算法训练营Day37 | 738. 单调递增的数字 | 968. 监控二叉树 | 贪心算法
贪心算法完结贪心算法很难总结规律。个人而言,如果一道题看上去非常符合 dp,但使用 dp 又显得太过复杂,那么就该考虑寻找贪心算法的解。区间问题,非常经典的贪心(右边界 yyds)。在406.根据身高重建队列和135.分发糖果中,输入数据有多个维度的考量。这时一定要先解决一个维度,再解决另一个。在 135 中,解决维度的难点在于后处理的维度也要考虑前一个维度的结果。在 406 中,找到优先处理的维度更为重要。53. 最大子序和巧妙地利用了数学的一些常识,从而获得了贪心性质;134. 加油站。
2023-08-22 14:03:32
198
原创 代码随想录算法训练营Day36 | 435. 无重叠区间 | 763. 划分字母区间 | 56. 合并区间
按区间的右边界,从小到大排序,然后对于重叠在一起的若干区间,保留其中有边界最小的那个(贪心:这样保留的区间对剩余区间的影响最小)。按区间的左边界,则直接计算需要删除的区间数:每当遇到重叠区间的时候,计数 +1,同时记录当前保留的区间中的最小右边界(与前一种思路一样的贪心)。将区间按左边界从小到大排序,不断更新当前划分的区间的最大右边界。当下一个区间与当前划分不重叠时,记录分割,并记录新的划分的左边界和右边界。此时,问题转化成了“对于给定的若干区间,找到最多的划分使得划分的区间之间互不重叠”。
2023-08-22 13:50:11
118
原创 代码随想录算法训练营Day35 | 860. 柠檬水找零 | 406. 根据身高重建队列 | 452. 用最少数量的箭引爆气球
将气球按照区间的结尾进行排序:如果检查到了区间终点,一个气球还没被射破,那就一定要在这个结尾处射一支箭,否则会无法射破所有气球。由于 k 是依赖于 h 的,优先处理 h 就能更好地利用 k 的信息。按照身高从大到小排序,如果身高相同则 k 小的优先。排序完成后,依次按照当前的 k 插入队列。因为身高从大到小(相同身高时,k 从小到大),当前插入的。按照身高进行从小到大的排序,将元素按照 k 的大小插入当前可以使用的空位。可以确认现在前面有 k 个大于等于 h 的元素,而之后插入的元素必然是小于等于 h的。
2023-08-22 06:46:02
133
原创 代码随想录算法训练营Day34 | 1005. K次取反后最大化的数组和 | 134. 加油站 | 135. 分发糖果
本题最重要的是保持贪心的思想来解题,即使题目很简单,但需要分类的贪心尚且是第一次遇到,要想清楚局部最优再开始解决贪心问题,否则就无法获得贪心的锻炼。局部最优:当前的区间剩余油量若是负数,则从其中任意位置出发都会断油,只有从后面的位置出发才有可能成功环绕。但这么写的复杂度很高,每次都需要遍历整个数组,不推荐,而且似乎没有体现出贪心的思想。每一次取反,都找到当前的最小值然后进行取反,进行 k 次即可。,其中第二个要求需要从左向右和从右向左的比较均满足条件。作为新的区间起点,重新记录区间内的总剩余油量。
2023-08-15 10:29:30
112
原创 代码随想录算法训练营Day28 | 93. 复原IP地址 | 78. 子集 | 90. 子集II
本题需要做去重,实际上和之前 组合总和II 以及之后排列去重的方法是一样的。在之前的组合、分割问题中,都是收集树的叶子节点。子集问题则是需要收集树的每一个节点。但子集问题的终止条件有所区别,本题并不需要 explicit 的终止条件,当。时,for loop 就不会执行,相当于自动结束了递归。是必不可少的,本题中还要额外记录分割的次数(可以从。子集问题没办法剪枝,因为从定义上就必须遍历所有的节点。题目的背景设置很复杂,但实际上是个分割问题。注意,去重之前要先将输入的数组排序。和之前的回溯问题一样,都需要。
2023-08-15 02:33:13
219
原创 代码随想录算法训练营Day23 | 669. 修剪二叉搜索树 | 108. 将有序数组转换为二叉搜索树 | 538. 把二叉搜索树转换为累加树 | 二叉树完结
和删除 BST 节点的操作看上去很相似,同样是通过返回节点来重构 BST。但实际上比删除节点要简单:当因为上下限而删除节点的时候,直接返回相对应的。以重构的方式进行节点删除,免除了记录父节点的麻烦,是一个非常精妙的方法。注意在普通二叉树的属性中,我用的是一般为后序,例如单纯求深度就用前序。同样可以通过双指针的方法,记录前一个节点的数值(已修改过),方便之后节点的累加。相比之下,删除特定节点需要在找到节点后手动进行删除,不能借助递归。如果数组长度为偶数,中间节点有两个,此时取任意一节点都可以,答案不唯一。
2023-08-15 00:26:27
108
原创 代码随想录算法训练营Day30 | 332. 重新安排行程 | 51. N皇后 | 37. 解数独 | 总结
总结篇组合问题:N个数里面按一定规则找出k个数的集合排列问题:N个数按一定规则全排列,有几种排列方式切割问题:一个字符串按一定规则有几种切割方式(切割线的组合)子集问题:一个N个数的集合里有多少符合条件的子集棋盘问题:N皇后,解数独等等。
2023-08-15 00:09:13
189
原创 代码随想录算法训练营Day32 | 122. 买卖股票的最佳时机II | 55. 跳跃游戏 | 45. 跳跃游戏II
本题依然要依靠最大覆盖范围来进行贪心,不同的是,上一题中关注的是最大覆盖范围,而本题关注的是增加覆盖范围所用的移动次数。如果发现走到当前覆盖范围的终点,却依然没有遇到全剧终点,那就只能选择多移动一次,在新的覆盖范围内查看能否覆盖全剧终点。这样的规定下,最大的收益可以。记录的是当前节点能够到达的最远节点,通过更新 dp 数组判断能否到达最后一个节点。“在每一个节点跳几步”是一个类似回溯的思路,对于本体来说过于复杂,也没有必要。所以对于每个元素,都可以更新自己覆盖的节点的 dp。的节点进行一次移动可以到达。
2023-08-14 13:12:41
137
原创 代码随想录算法训练营Day29 | 491. 递增子序列 | 46. 全排列 | 47. 全排列 II
遇到该元素值的时候,之前被当作去重了(如下图所示)。这种方法固然可以成立,但是会多很多不必要的检查,效率并不高。
2023-08-14 07:54:49
170
原创 代码随想录算法训练营Day27 | 39. 组合总和 | 40. 组合总和II | 131. 分割回文串
本题的难点在于分析出和组合的相似之处,从而能够以组合的思路解决字符串分割。同时,理解语义并且写出正确的单层搜索逻辑也很关键。按照简单思路得到所有的解之后,以 set 的形式去重,这样很容易导致超时。正确的做法是在遍历中进行去重,即。这个方法的思路有点复杂,很接近以前在二叉树删除节点中保持双指针记录父节点的方式。注意的是本题允许重复的元素,终止条件也是当前记录的子集和,所以对于递归的。另外的方法:不要使用已使用过的元素,显然可以额外维持一个数组。可以用 dp 优化判断回文串的方法,但不是重点,
2023-08-09 02:55:15
118
原创 代码随想录算法训练营Day25 | 216. 组合总和III | 17. 电话号码的字母组合
本题每一个数字代表的是不同集合,也就是求不同集合之间的组合。这和之前的题求解同一集合中的不同组合不一样。和 77 的组合其实非常相似,甚至这道题中的宽度是固定的(1-9)。需要注意的是,我的解法中使用了。来直接求解当前记录的和,如果是传递参数的方式来记录当前和,要记得在回溯的时候也把当前和进行回溯。
2023-08-07 17:34:20
151
原创 代码随想录算法训练营Day24 | 回溯算法 | 77. 组合
如下图所示,集合大小 n=4 是树的宽度,需要的子集大小 k=2 是树的深度。每次从集合中选取元素,可选择的范围(子树宽度)随着之前选择的进行而收缩,调整可选择的范围;非常经典的回溯处理:如果是固定长度的子集,可以用嵌套的 for loop 完成,只是很麻烦;适当的剪枝可以减少一些不必要的可能,但无法优化复杂度,因为没有改变穷举的本质。有的问题靠嵌套 for loop 是无法完成暴力搜索的,这时就需要回溯来有效地暴力解决问题,属于是无奈之举。所以,回溯函数也就是递归函数,指的都是一个函数。
2023-08-07 15:46:28
108
原创 代码随想录算法训练营Day20 | 654. 最大二叉树 | 617. 合并二叉树 | 700. 二叉搜索树中的搜索 | 98. 验证二叉搜索树
【代码】代码随想录算法训练营Day20 | 654. 最大二叉树 | 617. 合并二叉树 | 700. 二叉搜索树中的搜索 | 98. 验证二叉搜索树。
2023-08-04 14:55:44
80
1
原创 代码随想录算法训练营Day22 | 235. 二叉搜索树的最近公共祖先 | 701. 二叉搜索树中的插入操作 | 450. 删除二叉搜索树中的节点
返回值是非常有效的传递信息的方式!尤其在二叉树的修改中,返回值可以帮助以重构的方式完成修改,而无需保持双指针进行修改(树的结构决定了双指针还需要父节点的方向,太繁琐)。
2023-08-04 14:52:55
183
1
原创 代码随想录算法训练营Day21 | 530. 二叉搜索树的最小绝对差 | 501. 二叉搜索树中的众数 | 236. 二叉树的最近公共祖先
这一过程不断向上传递,直到有一个节点的左子树和右子树都显示遇到过目标节点,此时该节点即是两个目标节点的最近公共祖先。因为双指针能记录相邻两个元素的值,一个指向当前节点,一个指向之前的节点,能够很好解决 BST 中隔(很多)层记录上下限的问题。看到 BST 的第一反应一定是中序遍历,最大程度利用其单调性,同时通过 pre 指针来记录相邻的前一个节点,进行相关的操作。求两个节点的最近公共祖先,很自然的想法是找到两个节点的各自的祖先们,然后从根节点开始同时遍历,找到最后一个公共祖先即可。但是暴力算法需要排序,
2023-08-02 07:45:17
89
原创 代码随想录算法训练营Day18 | 513.找树左下角的值 | 112.路径总和 | 113.路径总和 II | 106.从中序与后序遍历序列构造二叉树 | 105.从前序与中序遍历序列构造二叉树
比较直观的遍历,搜索每一条根节点到叶子节点的 path,记录当前 path 的节点值的和。这种解法是搜索任意一条 path,所有的信息都局限于当前 path,所以需要返回值来回传当前 path 的结构,也就需要 bool 的返回值。递归的方法还是可行,记录当前得到过的叶子节点的(最大深度,节点值),遍历中不断进行更新,直到遍历完成。在处理过程中,另一个重要的性质是,中序数组和后序数组的大小应该是相等的,毕竟代表着同一棵树。这道题的一个考验点是递归函数的参数与返回值,不同的思路对于递归的返回值有不同的要求。
2023-07-31 10:06:23
273
1
原创 代码随想录算法训练营Day17 | 110.平衡二叉树 | 257. 二叉树的所有路径 | 404.左叶子之和
这保证了在进行下一次递归(不管是当前的右子树,或者是)的时候,path 数组会保持进行当前递归前的状态(就像是当前数组的 copy 一样)。但是与之前题目的区别在于,用于记录当前路径的 path 数组是会不断更新的,也就是说在执行完左子树的递归后,path 已经发生了改变,没办法直接再将其传入右子树的递归。需要注意的是递归的单层逻辑中,判断当前节点的左节点是否是叶子并不属于终止条件,而是决定了回传的值,属于是“中”的部分。题目中“左叶子”的定义:一个叶子节点,同时是另一个节点的左节点。
2023-07-30 08:11:50
178
1
原创 代码随想录算法训练营Day16 | 104. 二叉树的最大深度 | 111. 二叉树的最小深度 | 222. 完全二叉树的节点个数
对于完全二叉树而言,寻找到满二叉子树即可通过公式直接计算该树内的节点数量,并向父节点传递。这道题的递归终止条件比较复杂,当找到了满二叉子树的时候也应该直接返回(这也是低复杂度的来源,跳过了搜索所有满二叉子树的内部节点)。非常相似(高度是根节点到叶子节点的最远路径),所以还是可以后序遍历,从而得到最小深度。要小心的是对于空节点的处理,在后序解法中 None 是没可能成为叶子节点的,但却拥有最小的深度。:除了最后一层都是满的,最后一层的节点尽可能靠左分布。自己的前序遍历解法,和二叉树的几乎一模一样。
2023-07-28 14:46:26
168
1
原创 代码随想录算法训练营Day15 | 层序遍历 | 226. 翻转二叉树 | 101. 对称二叉树
递归的思路是较为简单的,在单层遍历中,交换当前节点的左右子节点即可。这题和上一题最大的不同在于,递归中的单层逻辑不能仅依靠当前节点的子节点(例如,比较子节点是否相等),还需要子节点的子节点。这里要比较的是外侧与外侧节点,内侧与内侧节点,所以对于左右子树来说,遍历(比较)顺序应该是相反的,即一个子树是“左右中”,一个子树是“右左中”。此题的重点思路是,只有完成了子节点(的子节点)的比较,才能得知当前节点的信息,从而决定是向上传递还是可以直接返回。遍历,即“当前节点的信息依赖于子节点的信息”。
2023-07-28 04:28:01
214
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人