自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 代码随想录算法训练营第六十天|84. 柱状图中最大的矩形

如果数组本身是降序的,例如 [8,6,4,2],在 8 入栈后,6 开始与8 进行比较,此时我们得到 mid(8),rigt(6),但是得不到 left。如果数组本身就是升序的,例如[2,4,6,8],那么入栈之后 都是单调递减,一直都没有走 情况三 计算结果的哪一步,所以最后输出的就是0了。那么因为本题是要找每个柱子左右两边第一个小于该柱子的柱子,所以从栈头(元素从栈头弹出)到栈底的顺序应该是从大到小的顺序!这里就涉及到了单调栈很重要的性质,就是单调栈里的顺序,是从小到大还是从大到小。

2024-05-29 15:17:32 669 1

原创 代码随想录算法训练营第五十九天|503.下一个更大元素II、42. 接雨水

因为一旦发现添加的柱子高度大于栈头元素了,此时就出现凹槽了,栈头元素就是凹槽底部的柱子,栈头第二个元素就是凹槽左边的柱子,而添加的元素就是凹槽右边的柱子。其实不用,栈里就存放下标就行,想要知道对应的高度,通过height[stack.top()] 就知道弹出的下标对应的高度了。遇到相同的元素,更新栈内下标,就是将栈里元素(旧下标)弹出,将新元素(新下标)加入栈中。答:不会减少,因为减法的下标是两边高的柱子的下标,不是当前柱子的下标。长就是通过柱子的高度来计算,宽是通过柱子之间的下标来计算,

2024-05-27 13:43:30 893

原创 代码随想录算法训练营第五十七天|739. 每日温度、496.下一个更大元素 I

因为我们遍历数组的时候,我们不知道之前都遍历了哪些元素,以至于遍历一个元素找不到是不是之前遍历过一个更小的,所以我们需要用一个容器(这里用单调栈)来记录我们遍历过的元素。这里我们要使用递增循序(再强调一下是指从栈头到栈底的顺序),因为只有递增的时候,栈里要加入一个元素i的时候,才知道栈顶元素在数组中右面第一个比栈顶元素大的元素是i。栈头到栈底的顺序,要从小到大,也就是保持栈里的元素为递增顺序。即:如果求一个元素右边第一个更大元素,单调栈就是递增的,如果求一个元素右边第一个更小元素,单调栈就是递减的。

2024-05-25 12:31:03 840

原创 代码随想录算法训练营第五十六天|647. 回文子串、516.最长回文子序列

如果这矩阵是从上到下,从左到右遍历,那么会用到没有计算过的dp[i + 1][j - 1],也就是根据不确定是不是回文的区间[i+1,j-1],来判断了[i,j]是不是回文,那结果一定是不对的。我们在判断字符串S是否是回文,那么如果我们知道 s[1],s[2],s[3] 这个子串是回文的,那么只需要比较 s[0]和s[4]这两个元素是否相同,如果相同的话,这个字符串s 就是回文串。那么dp[i][j]一定是取最大的,即:dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);

2024-05-23 15:27:36 948

原创 代码随想录算法训练营第五十五天|583. 两个字符串的删除操作、72. 编辑距离

那最后当然是取最小值,所以当word1[i - 1] 与 word2[j - 1]不相同的时候,递推公式:dp[i][j] = min({dp[i - 1][j - 1] + 2, dp[i - 1][j] + 1, dp[i][j - 1] + 1});因为 dp[i][j - 1] + 1 = dp[i - 1][j - 1] + 2,所以递推公式可简化为:dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);

2024-05-22 14:26:06 1022

原创 代码随想录算法训练营第五十四天|392. 判断子序列、115.不同的子序列

和 dp[i][j] = dp[i - 1][j];if (s[i - 1] == t[j - 1]),那么dp[i][j] = dp[i - 1][j - 1] + 1;= t[j - 1]),此时相当于t要删除元素,t如果把当前元素t[j - 1]删除,那么dp[i][j] 的数值就是 看s[i - 1]与 t[j - 2]的比较结果了,即:dp[i][j] = dp[i][j - 1];dp[i][j]:dp[i][j]表示s[0:i-1]的子序列中t[0:j-1]出现的次数。

2024-05-21 16:29:54 769

原创 代码随想录算法训练营第五十三天|1143.最长公共子序列、1035.不相交的线、53. 最大子数组和

那就看看text1[0, i - 2]与text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]与text2[0, j - 2]的最长公共子序列,取最大的。dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j]即:dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);根据dp[i]的定义,很明显dp[0]应为nums[0]即dp[0] = nums[0]。

2024-05-20 14:00:36 991

原创 代码随想录算法训练营第五十二天|300.最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组

举个例子A[0]如果和B[0]相同的话,dp[1][1] = dp[0][0] + 1,只有dp[0][0]初始为0,正好符合递推公式逐步累加起来。但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;根据dp[i][j]的定义,dp[i][j]的状态只能由dp[i - 1][j - 1]推导出来。

2024-05-19 16:59:41 760

原创 代码随想录算法训练营第五十天|309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费

如果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-05-17 15:22:57 658

原创 代码随想录算法训练营第四十九天|123.买卖股票的最佳时机III、188.买卖股票的最佳时机IV

一定是选最大的,所以 dp[i][1] = max(dp[i-1][0] - prices[i], dp[i - 1][1]);选最大的,所以 dp[i][1] = max(dp[i - 1][0] - prices[i], dp[i - 1][1]);所以dp[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2])那么dp[i][1]究竟选 dp[i-1][0] - prices[i],还是dp[i - 1][1]呢?此时还没有买入,怎么就卖出呢?

2024-05-16 15:36:56 755

原创 代码随想录算法训练营第四十八天|121. 买卖股票的最佳时机 、122.买卖股票的最佳时机II

那么第i天持有股票即dp[i][0],如果是第i天买入股票,所得现金就是昨天不持有股票的所得现金 减去 今天的股票价格 即:dp[i - 1][1] - prices[i]。同样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[0][0]和dp[0][1]推导出来。

2024-05-15 15:09:16 633

原创 代码随想录算法训练营第四十七天|198.打家劫舍、213.打家劫舍II、337.打家劫舍III

思路:当前房屋偷与不偷取决于前一个房屋和前两个房屋是否被偷了。所以这里就更感觉到,当前状态和前面状态会有一种依赖关系,那么这种依赖关系都是动规的递推公式。当然以上是大概思路,打家劫舍是dp解决的经典问题,接下来我们来dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]。(到第i个房间为止能偷的最多钱为dp[i])决定dp[i]的因素就是第i房间偷还是不偷。

2024-05-14 15:14:15 800

原创 代码随想录算法训练营第四十六天|139.单词拆分、动态规划:多重背包

从递推公式中可以看出,dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]就是递推的根基,dp[0]一定要为true,否则递推下去后面都都是false了。"apple", "pen" 是物品,那么我们要求 物品的组合一定是 "apple" + "pen" + "apple" 才能组成 "applepenapple"。"apple" + "apple" + "pen" 或者 "pen" + "apple" + "apple" 是不可以的,那么我们就是强调物品之间顺序。

2024-05-13 09:38:20 985

原创 代码随想录算法训练营第四十五天|70. 爬楼梯 (进阶)、322. 零钱兑换、279.完全平方数

凑足总额为j - coins[i]的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1就是dp[j](考虑coins[i])(防止递推公式的值被初始值覆盖)既然递归公式是 dp[i] += dp[i - j],那么dp[0] 一定为1,dp[0]是递归中一切数值的基础所在,如果dp[0]是0的话,其他数值都是0了。本题呢,dp[i]有几种来源,dp[i - 1],dp[i - 2],dp[i - 3] 等等,即:dp[i - j]

2024-05-11 17:14:52 889

原创 代码随想录算法训练营第四十四天|动态规划:完全背包理论基础、518. 零钱兑换 II、377. 组合总和 Ⅳ

dp[0]=1还说明了一种情况:如果正好选了coins[i]后,也就是j-coins[i] == 0的情况表示这个硬币刚好能选,此时dp[0]为1表示只选coins[i]存在这样的一种选法。因为递推公式dp[i] += dp[i - nums[j]]的缘故,dp[0]要初始化为1,这样递归其他dp[i]的时候才会有数值基础。首先dp[0]一定要为1,dp[0] = 1是 递归公式的基础。下标非0的dp[j]初始化为0,这样累计加dp[j - coins[i]]的时候才不会影响真正的dp[j]

2024-05-10 14:58:10 885

原创 代码随想录算法训练营第四十三天|1049. 最后一块石头的重量 II、494. 目标和、474.一和零

接下来就是如何初始化dp[j]呢,因为重量都不会是负数,所以dp[j]都初始化为0就可以了,这样在递归公式dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);相对于 01背包,本题中,石头的重量是 stones[i],石头的价值也是 stones[i] ,可以 “最多可以装的价值为 dp[j]” == “最多可以背的重量为dp[j]”01背包的递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

2024-05-08 15:53:49 711

原创 代码随想录算法训练营第四十二天|动态规划:01背包理论基础、动态规划:01背包理论基础(滚动数组)

在一维dp数组中,dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j]。

2024-05-06 00:49:41 828

原创 代码随想录算法训练营第四十一天|343.整数拆分、96.不同的二叉搜索树

那么从1遍历j,比较(i - j) * j和dp[i - j] * j 取最大的。从递归公式上来讲,dp[以j为头结点左子树节点数量] * dp[以j为头结点右子树节点数量] 中以j为头结点左子树节点数量为0,也需要dp[以j为头结点左子树节点数量] = 1, 否则乘法的结果就都变成0了。j的结束条件是 j < i - 1 ,其实 j < i 也是可以的,不过可以节省一步,例如让j = i - 1,的话,其实在 j = 1的时候,这一步就已经拆出来了,重复计算,所以 j < i - 1。

2024-04-29 22:49:04 1059

原创 代码随想录算法训练营第三十九天|62.不同路径、63. 不同路径 II

从递归公式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-28 23:30:03 556

原创 代码随想录算法训练营第三十八天|动态规划理论基础、509.斐波那契数、70.爬楼梯、746.使用最小花费爬楼梯

那么 dp[0] 应该是多少呢?根据dp数组的定义,到达第0台阶所花费的最小体力为dp[0],那么有同学可能想,那dp[0] 应该是 cost[0],例如 cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] 的话,dp[0] 就是 cost[0] 应该是1。看一下递归公式,dp[i]由dp[i - 1],dp[i - 2]推出,既然初始化所有的dp[i]是不可能的,那么只初始化dp[0]和dp[1]就够了,其他的最终都是dp[0]dp[1]推出。

2024-04-27 00:22:22 2157

原创 代码随想录算法训练营第三十七天|738.单调递增的数字

例如:98,一旦出现strNum[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum[i - 1]--,然后strNum[i]给为9,这样这个整数就是89,即小于98的最大的单调递增整数。从前向后遍历的话,遇到strNum[i - 1] > strNum[i]的情况,让strNum[i - 1]减一,但此时如果strNum[i - 1]减一了,可能又小于strNum[i - 2]。题意很简单,那么首先想的就是暴力解法了,来我替大家暴力一波,结果自然是超时!

2024-04-26 00:43:28 473

原创 代码随想录算法训练营第三十六天|435. 无重叠区间、763.划分字母区间、56. 合并区间

即intervals[i]的左边界

2024-04-24 21:07:09 494

原创 代码随想录算法训练营第三十五天|860.柠檬水找零、406.根据身高重建队列、452. 用最少数量的箭引爆气球

可以看出首先第一组重叠气球,一定是需要一个箭,气球3,的左边界大于了 第一组重叠气球的最小右边界,所以再需要一支箭来射气球3了。按照身高排序之后,优先按身高高的people的k来插入,后序插入节点也不会影响前面已经插入的节点,最终按照k的规则完成了队列。如果按照k来从小到大排序,排完之后,会发现k的排列并不符合条件,身高也不符合条件,两个维度哪一个都没确定下来。此时大家就发现 情况一,情况二,都是固定策略,都不用我们来做分析了,而唯一不确定的其实在情况三。局部最优:当气球出现重叠,一起射,所用弓箭最少。

2024-04-23 22:15:25 859

原创 代码随想录算法训练营第三十四天|1005.K次取反后最大化的数组和、134. 加油站、135. 分发糖果

如果 ratings[i] > ratings[i + 1],此时candyVec[i](第i个小孩的糖果数量)就有两个选择了,一个是candyVec[i + 1] + 1(从右边这个加1得到的糖果数量),一个是candyVec[i](之前比较右孩子大于左孩子得到的糖果数量)。i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置,因为这个区间选择任何一个位置作为起点,到i这里都会断油,那么起始位置从i+1算起,再从0计算curSum。

2024-04-22 20:50:22 977

原创 代码随想录算法训练营第三十二天|122.买卖股票的最佳时机II、55.跳跃游戏、45.跳跃游戏II

那么根据 prices 可以得到每天的利润序列:(prices[i] - prices[i - 1]).....(prices[1] - prices[0])。相当于(prices[3] - prices[2]) + (prices[2] - prices[1]) + (prices[1] - prices[0])。i 每次移动只能在 cover 的范围内移动,每移动一个元素,cover 得到该元素数值(新的覆盖范围)的补充,让 i 继续移动下去。从图中可以发现,其实我们需要收集每天的正利润就可以,

2024-04-21 21:31:09 673

原创 代码随想录算法训练营第三十一天|贪心算法理论基础、455.分发饼干、376. 摆动序列、53.最大子序和

虽然这个例子很极端,但可以表达这么个意思:刷题或者面试的时候,手动模拟一下感觉可以局部最优推出整体最优,而且想不到反例,那么就试一试贪心。再举一个例子如果是 有一堆盒子,你有一个背包体积为n,如何把背包尽可能装满,如果还每次选最大的盒子,就不行了。如果 -2 1 在一起,计算起点的时候,一定是从 1 开始计算,因为负数只会拉低总和,这就是贪心贪的地方!靠自己手动模拟,如果模拟可行,就可以试一试贪心策略,如果不可行,可能需要动态规划。做题的时候,只要想清楚 局部最优 是什么,如果推导出全局最优,其实就够了。

2024-04-20 01:13:39 725

原创 代码随想录算法训练营第二十九天|491.递增子序列、46.全排列、46.全排列II

因为排列问题,每次都要从头开始搜索,例如元素1在[1,2]中已经使用过了,但是在[2,1]中还要再使用一次1。而本题求自增子序列,是不能对原数组进行排序的,排完序的数组都是自增子序列了。最大的不同就是for循环里不用startIndex了。中我们是通过排序,再加一个标记数组来达到去重的目的。,接下来看一看排列问题。这里又涉及到去重了。

2024-04-17 22:28:06 508

原创 代码随想录算法训练营第二十八天|93.复原IP地址、78.子集、90.子集II

从图中可以看出,同一树层上重复取2 就要过滤掉,同一树枝上就可以重复取2,因为同一树枝上元素的集合才是唯一子集!其实子集也是一种组合问题,因为它的集合是无序的,子集{1,2} 和 子集{2,1}是一样的。其实只要意识到这是切割问题,切割问题就可以使用回溯搜索法把所有可能性搜出来,和刚做过的。从图中红线部分,可以看出遍历这个树的时候,把所有节点都记录下来,就是要求的子集集合。如果把 子集问题、组合问题、分割问题都抽象为一棵树的话,用示例中的[1, 2, 2] 来举例,如图所示: (

2024-04-17 00:16:32 449

原创 代码随想录算法训练营第二十七天|39.组合总和、40.组合总和II、131.分割回文串

以及上面的版本一的代码大家可以看到,对于sum已经大于target的情况,其实是依然进入了下一层递归,只是下一层递归结束判断的时候,会判断sum > target的话就返回。注意图中叶子节点的返回条件,因为本题没有组合数量要求,仅仅是总和的限制,所以递归没有层数的限制,只要选取的元素总和超过target,就返回!的区别是:本题没有数量要求,可以无限重复,但是有总和的限制,所以间接的也是有个数的限制。此时可以发现,切割问题的回溯搜索的过程和组合问题的回溯搜索的过程是差不多的。

2024-04-15 21:30:25 2078

原创 代码随想录算法训练营第二十五天|216.组合总和III、17.电话号码的字母组合

图中可以看出遍历的深度,就是输入"23"的长度,而叶子节点就是我们要收集的结果,输出["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]。例如 k = 2,n = 4的话,就是在集合[1,2,3,4,5,6,7,8,9]中求 k(个数) = 2, n(和) = 4的组合。从示例上来说,输入"23",最直接的想法就是两层for循环遍历了吧,正好把组合的情况都输出了。本题就是在[1,2,3,4,5,6,7,8,9]这个集合中找到和为n的k个数的组合。

2024-04-14 21:23:52 350

原创 代码随想录算法训练营第二十四天|回溯算法理论基础、77.组合

来举一个例子,n = 4,k = 4的话,那么第一层for循环的时候,从元素2开始的遍历都没有意义了。因为回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案,如果想让回溯法高效一些,可以加一些剪枝的操作,但也改不了回溯法就是穷举的本质。图中每一个节点(图中为矩形),就代表本层的一个for循环,那么每一层的for循环从第二个数开始遍历的话,都没有意义,都是无效遍历。,这样就把这棵树全遍历完了,一般来说,搜索叶子节点就是找的其中一个结果了。,是的,我指的是所有回溯法的问题都可以抽象为树形结构!

2024-04-12 17:51:07 959

原创 代码随想录算法训练营第二十三天|669. 修剪二叉搜索树 、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树

补充:整个代码逻辑基于分治法的思想,将一个大问题(构建整个二叉搜索树)分解为多个小问题(构建子树),然后递归地解决这些子问题,最终组合成整体的解决方案。由于递归的深度是O(log n),所以递归调用栈使用的空间是O(log n)为递归过程中栈的开销,平均情况下为 O(log⁡n),最坏情况下树呈现链状,为 O(n)。因为数组大家都知道怎么遍历啊,从后向前,挨个累加就完事了,这换成了二叉搜索树,看起来就别扭了一些是不是。其中 n是二叉搜索树的节点数。然后再发现这是一棵二叉搜索树,二叉搜索树啊,这是有序的啊。

2024-04-11 15:38:22 529

原创 代码随想录算法训练营第二十二天|235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

因为是有序树,所以 如果 中间节点是 q 和 p 的公共祖先,那么 中节点的数组 一定是在 [p, q]区间的。搜索树的节点删除要比节点增加复杂的多,有很多情况需要考虑,做好心理准备。例如插入元素10 ,需要找到末尾节点插入便可,一样的道理来插入元素15,插入元素0,插入元素6,空间复杂度:O(n),最坏情况下,二叉树是一条链,因此递归需要 O(n) 的栈空间。,可以方便的从上向下查找目标区间,遇到目标区间内的节点,直接返回。时间复杂度:O(n),其中 n为二叉树的节点个数。空间复杂度:O(n)

2024-04-10 17:13:13 484 1

原创 代码随想录算法训练营第二十一天|530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

首先如果不是二叉搜索树的话,应该怎么解题,是二叉搜索树,又应该如何解题,两种方式做一个比较,可以加深大家对二叉树的理解。如果不是二叉搜索树,最直观的方法一定是把这个树都遍历了,用map统计频率,把频率排个序,最后取前面高频的元素的集合。遍历有序数组的元素出现频率,从头遍历,那么一定是相邻两个元素作比较,然后就把出现频率最高的元素输出就可以了。遇到在二叉搜索树上求什么最值啊,差值之类的,就把它想成在一个有序数组上求最值,求差值,这样就简单多了。注意是二叉搜索树,二叉搜索树可是有序的。这就考察对树的操作了。

2024-04-09 21:58:07 283

原创 代码随想录算法训练营第二十天|654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树

在最坏的情况下,数组严格递增或递减,需要递归 n层,第 i (0≤i

2024-04-09 00:14:50 899

原创 代码随想录算法训练营第十八天|513.找树左下角的值、112. 路径总和、113.路径总和ii、106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树

可以使用前序遍历(当然中序,后序都可以,因为本题没有 中间节点的处理逻辑,只要左优先就行),保证优先左边搜索,然后记录深度最大的叶子节点,此时就是树的最后一行最左边的值。1.确定递归函数的参数和返回类型:参数:需要二叉树的根节点,还需要一个计数器,这个计数器用来计算二叉树的一条边之和是否正好是目标和,计数器为int型。方法对二叉树进行了类似前序遍历的遍历(即先处理当前节点,然后遍历左子树,最后遍历右子树),但有一个关键的区别:在遍历过程中,它记录了遍历到的最大深度,并据此更新最底层最左边节点的值。

2024-04-07 16:58:56 701

原创 代码随想录算法训练营第十七天|110.平衡二叉树、257. 二叉树的所有路径、404.左叶子之和

然后是递归和回溯的过程,上面说过没有判断cur是否为空,那么在这里递归的时候,如果为空就不进行下一层递归了。使用递归法,递归的遍历顺序为后序遍历(左右中),是因为要通过递归函数的返回值来累加求取左叶子数值之和。这道题目要求从根节点到叶子的路径,所以需要前序遍历,这样才方便让父节点指向孩子节点,找到对应的路径。因为是前序遍历,需要先处理中间节点,中间节点就是我们要记录路径上的节点,先放进path中。要传入根节点,记录每一条路径的path,和存放结果集的result,这里递归不需要返回值。空间复杂度:O(n)

2024-04-05 18:04:23 383 1

原创 代码随想录算法训练营第十六天|104.二叉树的最大深度、111.二叉树的最小深度、222.完全二叉树的节点个数

反之,右子树为空,左子树不为空,最小深度是 1 + 左子树的深度。3.确定单层递归的逻辑:先求它的左子树的深度,再求右子树的深度,最后取左右深度最大的数值 再+1 (加1是因为算上当前中间节点)就是目前节点为根节点的树的深度。3.确定单层递归的逻辑:先求它的左子树的节点数量,再求右子树的节点数量,最后取总和再加一 (加1是因为算上当前中间节点)就是目前节点为根节点的节点数量。1.确定递归函数的参数和返回值:参数就是传入树的根节点,返回就返回以该节点为根节点二叉树的节点数量,所以返回值为int类型。

2024-04-05 00:56:21 817 1

原创 代码随想录算法训练营第十五天|102.二叉树的层序遍历、226.翻转二叉树、101.对称二叉树

空间复杂度:O(n) ,在最坏的情况下,当二叉树完全不平衡时(例如,所有节点都只有左子节点或只有右子节点,变成一个链表结构),递归调用栈的深度可能达到n。因此,总的空间复杂度是O(n)。对于二叉树是否对称,要比较的是根节点的左子树与右子树是不是相互翻转的,理解这一点就知道了其实我们要比较的是两个树(这两个树是根节点的左右子树),所以在递归遍历的过程中,也是要同时遍历两棵树。空间复杂度O(n):在最坏的情况下,即当二叉树的最后一层节点全部被加入队列时,队列的大小将达到最大,即存储了二叉树中几乎所有的节点。

2024-04-03 22:55:02 741 1

原创 代码随想录算法训练营第十四天|二叉树理论基础、二叉树的递归遍历、二叉树的迭代遍历

写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。分析一下为什么刚刚写的前序遍历的代码,不能和中序遍历通用呢,因为前序遍历的顺序是中左右,先访问的元素是中间节点,要处理的元素也是中间节点,所以刚刚才能写出相对简洁的代码,之前我们讲栈与队列的时候,就说过栈其实就是递归的一种实现结构(递归的底层实现是栈),也就说前中后序遍历的逻辑其实都是可以借助栈使用递归的方式来实现的。

2024-04-02 22:05:57 725 1

空空如也

空空如也

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

TA关注的人

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