自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 代码随想录总结

再到二叉树、回溯算法、贪心算法、动态规划、单调栈,我深刻地体会到了网上流行的一句话,“一根笔,一杯茶,一道leetcode做一天”,有的题自己思考一直都想不到,不妨看一下题解,不仅可以节省时间,还可以减少自己的痛苦,通过学习前辈的方法,看看能否内化。刷题不能只看数量,要看质量,我发现我之前做过的题目,第二次再做时又出现问题了,不能背答案,要自己理解,自己想明白,融会贯通,有的题目真的是换汤不换药,仅仅是应用场景改变,核心代码并没有改变。值得一提的是,代码随想录的顺序环环相扣,足以可见花费了好多心思。

2025-01-11 15:46:25 216

原创 Day62 图论part11

初始化的时候把 k =0 的 i 和j 对应的数值都初始化了,这样才能去计算 k = 1 的时候 i 和 j 对应的数值。这就好比是一个三维坐标,i 和j 是平层,而k是垂直向上的。dp数组如何初始化:需要初始化K=0的情况,K=0,就是两个节点直接相连,没有中间节点,所以直接赋值边的权值就可以了。Floyd 算法代码很简单,但真正理解起原理 还是需要花点功夫,大家在看代码的时候,会发现 Floyd 的代码很简单,甚至看一眼就背下来了,但我为了讲清楚原理,本篇还是花了大篇幅来讲解。

2024-12-30 21:58:02 1013

原创 Day60 图论part10

对于使用队列优化的bellman_ford算法,其实每个节点入度最大是n-1,也就是每个节点最多和n-1个节点直接相连,也就是进入队列最多n-1次,如果进入队列的次数超过这个数,那么一定是出现了负权回路,所以我们只需要int[] count 判断节点加入到队列的次数,每次加入队列,次数加1,然后判断count,如果大于等于n,那么也把标志flag设置为true,并且要把队列里面的元素全部弹出,因为break只能退出for循环,不能退出while循环。但真正有效的松弛,是基于已经计算过的节点在做的松弛。

2024-12-30 13:20:55 981

原创 Day59 图论part09

由于我们是在弹出队列的时候,再标记节点,所以会导致有些节点被反复加入到队列里面,这时候需要if(isVisited[point])然后跳过循环。isVisited[edge.end] && minDist[point] + edge.val < minDist[edge.end])我们是在节点有更新的时候,再把节点加入到队列里面,但这样还是会重复加入一些节点,所以必须有if(isVisited[point])这个跳过重复的节点。如果权重为负数,最短路径可能会在访问节点后继续缩短,这会违反算法的基本假设。

2024-12-29 22:07:21 789

原创 Day58 图论part08

2.本题初始化的时候, int[][] graph = new int[n+1][n+1];移除节点其实就是找到当前节点指向的终点,然后把这个终点的入度减1。保存每个节点指向的终点,其实就是邻接表。3.最后如果结果集的大小不等于节点数,那么说明图中一定有 有向环,找不到入度为0 的节点了,也就没法把这个有向图转成线性的排序。当然拓扑排序也要检测这个有向图 是否有环,即存在循环依赖的情况,因为这种情况是不能做线性排序的。后面几天都是最短路系列了,对于最短路系列,我的建议是,如果第一次接触最短路算法的话,

2024-12-26 22:49:01 716

原创 Day57 图论part07

因为第一个节点的minDist = 10001,是小于Integer.MAX_VALUE的,所以mindist会被更新为10001,但后面的节点minDist也是10001,就不会再更新下标和mindist了。kruskal算法是对边进行处理,就是先用一个集合来收集所有的边,然后对边按照权值大小排序,然后我们遍历排序后的集合,判断每条边的两个端点是否在同一个集合里,如果在的话,加入就会成环。如果 一个图中,节点多,但边相对较少,那么使用Kruskal 更优。相反,如果节点少,但边多,就使用prime算法。

2024-12-26 16:55:35 1051

原创 Day56 图论part06

2.由于这道题是有向图,所以需要处理两种情况,一种是入度为2的节点对应的两条边,一种情况是没有入度为2的节点,但是有环。我们可以把入度为2的边逆序保存起来,遍历的时候正序遍历这些边,如果碰到删除某条边,还可以为树的,那这条边就是我们要找的。这道题保存入度为2的边,是保存其下标,然后凭借其下标在存储边的集合里面找到具体的边。这道题我们就从前往后判断两个节点是否在一个集合里面,如果在同一个集合里面,说明两个节点的根节点是同一个,再把这条边加上去,那么就会形成环,这个就是我们需要寻找的冗余连接。

2024-12-25 22:23:17 922

原创 Day55 图论part05

1.直接套用并查集模板。使用 join(int u, int v) farther[v] = u;将每条边加入到并查集。最后 isSame(int u, int v) 判断是否是同一个根 就可以了。不先寻根,无法保证两个集合的连通性被正确处理,因为不同集合可能通过非根节点错误地连接,形成多棵树混乱的情况。,明确并查集解决什么问题,代码如何写,对后面做并查集类题目很有帮助。并查集裸题,学会理论基础后,本题直接可以直接刷过。1.并查集主要有两个功能:主要就是集合问题。并查集理论基础很重要。

2024-12-25 17:42:57 564

原创 Day53 图论part04

如果我们使用一维的数组,那么2,4其实就表示从1出发,可以访问到2节点,然后再从2出发可以访问到4节点,也就是1可以访问到4。当前访问的节点如果是 true ,说明是访问过的节点,那就终止本层递归,如果不是true,我们就把它赋值为true,因为这是我们处理本层递归的节点。1.这道题就是比较暴力 的解法,我们遍历每个地图,碰到陆地,就遍历这块陆地的上下左右四个边,然后判断这条边是否是周长,也就是看这条边是否是边界,或者是否和海洋相邻,如果该边符合要求,就周长加1,然后对四条边都进行同样的判断处理。

2024-12-25 12:08:46 1103

原创 Day52 图论part03

最终还留下的陆地就是结果。1.本题的思路和上一道题差不多,只不过碰到边缘陆地,通过BFS或者DFS,我们是把该陆地和与该陆地连接的陆地设置为2,然后再次遍历整个地图的时候,我们把孤岛,也就是1改成0,然后再把2改回为1。2.最后需要对全为陆地的特殊情况进行处理,全为陆地的话,HashMap里面mark为2的面积就是最大的陆地面积(因为mark是从2开始标记的)。2.这道题一开始对题目理解错了,以为是面积为1的岛屿就是孤岛,其实孤岛的面积不一定为1,孤岛是指位于矩阵内部、所有单元格都不接触边缘的岛屿。

2024-12-24 20:01:22 646

原创 Day51 图论part02

另一种是for循环里面调用递归函数的时候,加上判断条件,这样递归函数里面传入的都是合法的节点,这样也就不用在写上终止条件了。3.整体思路就是如果是未被标记的陆地,result加1,然后把该节点加入到队列里面,然后做个标记,然后把该节点弹出,在以弹出的节点为中心,上下左右搜索合法的节点加入到队列里面。1.广搜的写法有一种会超时,如果从队列拿出节点,再去标记这个节点走过,会导致很多节点重复加入队列,相当于如果该节点符合要求,会被重复加入到队列里面,因为如果该节点不被弹出的话,是不会被标记的,这样就会导致超时。

2024-12-24 10:26:18 418

原创 Day50 图论part01

邻接矩阵是从节点的角度来表示图,使用二维数组来表示图结构。例如: grid[2][5] = 6,表示 节点 2 连接 节点5 为有向图,节点2 指向 节点5,边的权值为6。如果想表示无向图,即:grid[2][5] = 6,grid[5][2] = 6,表示节点2 与 节点5 相互连通,权值为6。邻接链表一般是通过数组+链表,数组里面就存放节点,链表里面存放的是节点可以连通的节点,也就是边。比如1-3-5 表示的是节点1 指向 节点3 和 节点5,并不是节点1连着3,3后面连着5,这点要搞清楚。

2024-12-22 20:57:46 526

原创 Day49 单调栈part02

这和接雨水的题目不一样,接雨水的题目是保存左边最大的元素,并不是第一个元素。所以为了找到左边第一个元素的下标,我们首先初始化0的下标为-1(避免while无限循环),然后先假设 left = i -1 ,然后用while循环更新left。2.单调栈就是寻找左边第一个小的下标和右边第一个小的下标。还是使用栈,按照栈头到栈尾递增的顺序来存放元素下标,如果当前元素小于等于栈顶元素,就直接加入栈就行,如果大于栈顶元素,还是循环判断,先弹出栈顶元素作为中间元素,当前比较的元素作为右边,最新的栈顶元素就是左边。

2024-12-21 23:29:53 973

原创 Day48 单调栈part01

如果当前元素比栈顶元素大的话,应该记录结果到result里面,result的下标就是栈顶元素,然后把栈顶元素弹出,再一直循环比较,直到把小元素全部弹出(当然前提是当前栈不为空),再把当前元素压入栈里面。然后在弹出元素的时候,判断这个元素是否在nums1里面,如果是nums1里面的元素,就加入到result里面。3.如果求一个元素右边第一个更大元素,单调栈的顺序(从栈顶到栈底的顺序)就是递增的,就是求更大的元素,如果栈顶碰到一个更大的元素,我们应该把小元素弹出去,然后把大元素加进来,这样其实就是递增的顺序。

2024-12-21 17:06:19 419

原创 Day46 动态规划part13

2.方法2更加好理解,对于 dp[i+1][j-1] ,一定要讨论 j - i == 0和 j - i == 1这两种情况,确保 j - i > 1,才是我们想要的dp[i+1][j-1],一定要确保 j - 1 >= i+1,也就是 j - i >= 2,才是我们正确理解的那个dp[i-1][j+1]。3.对于回文子串的题目,最好都按照 "dp[i][j]表示下标范围[i j]的字符串内回文子串最大长度"定义dp数组,因为对于回文子串的题目,dp[i][j]一般是和dp[i+1][j-1]相关的。

2024-12-20 22:54:33 907

原创 Day45 动态规划part12

如果第一个字符相同dp[1][1] = dp[0][0] + dp[0][1],dp[1][1]显然为1,那么dp[0][0]应该为1,并且dp[i][0]应该也初始化为1,因为也就是把以i-1为结尾的s,删除所有元素,出现空字符串的方法个数就是1。2.确定递推公式:当word1[i - 1] 与 word2[j - 1]相同的时候,我们不需要进行删除操作, dp[i][j] = dp[i-1][j-1];所以dp[i][j] = dp[i-1][j];

2024-12-20 16:19:01 961

原创 Day44 动态规划part11

6.返回值应该是最大的 dp[i],所以可以初始化 res = nums[0]来保存最大的dp[i],然后直接放在递推公式的for循环体里面计算就行,不用单独一个for循环。本题要求是不连续的dp数组的定义是dp[i][j] 表示字符串1下标范围[0 i-1]和字符串2下标范围[0 j-1]的最长公共子序列长度为dp[i][j]。最长重复子数组 的区别,就是子序列和连续子序列的区别,主要体现在对dp数组的定义,以及对元素不同的处理逻辑,最长重复子数组 如果元素不同,就直接为0,然后最后返回结果,就返回。

2024-12-19 16:52:01 1044

原创 Day43 动态规划part10

所以假如两个数组的第0个元素都相同,那么dp[1][1]应该是1,所以dp[0][0]应该是0,所以dp[ i ][0]和dp[0][ j ]都应该是初始化为0。2.递推公式: 我们需要另一个for循环遍历nums[i]之前的元素,如果nums[i] > nums[j],那么就需要在这个尾元素的基础上加1,就是dp[ j ] + 1,然后我们需要不断更新dp[ i ],找到dp[ j ] + 1最大的那一个。5.输出应该是所有dp[ i ]里面最大的那一个。

2024-12-18 22:59:54 1035

原创 Day42 动态规划part09

因为本题我们有冷冻期,而冷冻期的前一天,只能是 「今天卖出股票」状态,如果是 「不持有股票状态」那么就很模糊,因为不一定是 卖出股票的操作。dp数组就有4个状态了://dp[i][0] 持有股票的状态 //dp[i][1]保持卖出股票的状态 //dp[i][2]当天卖出股票 //dp[i][3]冷冻期。边界条件不清楚的可以代入具体数值看看,然后初始化一般是第0天状态的初始化,不清楚应该初始化多少合适的,也是可以代入某一天看看应该初始化多少来满足递推公式,一般是看第1天,来初始化第0天。

2024-12-18 17:07:47 749

原创 Day41 动态规划part08

1.这道题和上一题的最大区别就是dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] - prices[i]);分析持有股票的情况,如果之前没有持有股票,然后再买入股票,这种情况需要考虑因为之前的买卖操作,此时手头的现金可能就不再是0了,可能会有之前买卖的利润即:dp[i - 1][1],所以dp[i - 1][1] - prices[i]。对dp[i][0]和dp[i][1]的更新就像121题,然后对dp[i][2]和dp[i][3]的更新就是122题。

2024-12-17 22:23:40 1216

原创 Day39 动态规划part07

3.由递推公式知道,我们需要对dp[ 0 ]和dp[ 1 ]进行初始化,dp[0] = nums[0];对dp[ 1] 初始化的时候,得考虑长度是否为1,如果为1的话,dp[ 1 ]的数组就越界了。如果偷的话,那就是i-1不考虑,考虑i-2,那就是dp[i-2] + nums[i]。2.返回值和传入参数:这边返回值就是dp数组,dp数组长度为2,dp[0]表示偷当前节点获得的最大金币;这也是dp数组的下标和含义。也就是每进入一层递归,也就是对应每一个树节点,都会有一个新的dp数组来对应保存当前节点的状态。

2024-12-16 22:33:44 1669

原创 Day38 动态规划part06

3.if(i >= len && dp[i - len] && word.equals(s.substring(i - len, i)) )如果满足这个条件,那么dp[ i ]就是true。初始化 dp[ 0 ] = 0,不用纠结,通过递推公式推一下dp[ 1 ]就知道,应该把dp[ 0 ]初始化为0。4.初始化:由递推公式知道,dp[0] = 0,但其他非0下标应该被初始化为最大的整数,这样dp[ j ]才会进行正常的更新,而不会一直被初始值覆盖。dp[ j ]表示容量为j的背包,装满所需的最少物品数;

2024-12-15 22:28:38 556

原创 Day37 动态规划part05

1.前序遍历为什么可以先背包后物品呢,因为由递推公式dp[j] = Math.max(dp[j], dp[j-weight[i]] + value[i]);这样dp[j-weight[i]] 表示的就是新的已经处理的数据,代表当前物品可能已经被加入到背包里面了。对于二维的dp数组,递推公式应该是dp[i][j] = Math.max(dp[ i-1 ][j], dp[ i ][j-weight[i]] + value[i])。1.dp[j]代表的是凑成容量为j的背包,有dp[i]种方法;

2024-12-05 21:07:45 713

原创 Day36 动态规划part04

然后背包容量为0的时候,不放物品也是一种方法(这个不需要纠结,只需要自己推一下dp数组,例如dp[1][1] = 2,就是拿物品1和拿物品0两种方法,dp[i-1][j] = 1,那么dp[i-1][j-nums[i]显然是1)我们对第一行初始化,仔细要把do[0][nums[0]] = 1.然后是对第一列初始化。相对于 01背包,本题中,石头的重量是 stones[i],石头的价值也是 stones[i] ,可以 “最多可以装的价值为 dp[j]” == “最多可以背的重量为dp[j]”

2024-12-04 17:00:13 1807

原创 Day35 动态规划part03

正式开始背包问题,背包问题还是挺难的,虽然大家可能看了很多背包问题模板代码,感觉挺简单,但基本理解的都不够深入。如果是直接从来没听过背包问题,可以先看文字讲解慢慢了解 这是干什么的。如果做过背包类问题,可以先看视频,很多内容,是自己平时没有考虑到位的。背包问题,力扣上没有原题,大家先了解理论,今天就安排一道具体题目。详细布置。

2024-12-03 10:54:48 1015

原创 Day33 动态规划part02

那为什么不对j也做拆分呢?4.由dp[i] = Math.max(dp[i], Math.max(j * (i-j), j * dp[i-j]))可以知道,dp[i]是依赖于dp[i-j]的,比如说9的拆分结果,是依赖于8的,所以我们遍历的时候一定是从前向后遍历,先有dp[i - j]再有dp[i]。3.递归公式dp[i][j] = dp[i-1][j] + dp[i][j-1]这里,如果当前是障碍物,我们应该直接设置为0,所以变成dp[i][j] = (obstacleGrid[i][j] == 1?

2024-12-02 22:09:10 676

原创 Day 32 动态规划part01

自然的就可以得到递推公式为 dp[i] = Math.min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2]);dp[i-1] + cost[i-1]表示的是dp[i - 1] 跳到 dp[i] 需要花费 dp[i - 1] + cost[i - 1]。在推导dp[i]的时候,一定要时刻想着dp[i]的定义,否则容易跑偏。然后不断往后移动就行。不考虑dp[0]如何初始化,只初始化dp[1] = 1,dp[2] = 2,然后从i = 3开始递推,这样才符合dp[i]的定义。

2024-11-30 20:33:56 1101

原创 Day31 贪心算法 part05

最后一个难点就是我们不应该是直接把当前数字变成9,而是设置一个flag,让flag后面的数字全变成9,这是为了防止1000,这种情况,如果不使用flag,就是900,而不是999。如果intervals[i][0] <= intervals[i-1][1]说明当前段的边界和上一个边界有重叠,然后对当前边界进行跟新,需要更新当前边界的左边取最小值,然后更新当前边界的右边取最大值。可以看看贪心算法的总结,贪心本来就没啥规律,能写出个总结篇真的不容易了。本题是贪心和二叉树的一个结合,比较难,一刷大家就跳过吧。

2024-11-29 22:45:39 1942 2

原创 Day 30 贪心算法 part04

我们是把右边界更新为更短的那一条边界,其实这里面的思路相当于([1,2][1,3])我们把[1,3]更新为[1,2],也就是去除了长度更长的那一段,因为去除了长度更长的那一段,那它重叠的机会就更少,这就是贪心所在。我们只需要不断的更新最大的右边界,当下一个字符的左边界,大于上一个字符的右边界,就找到分割点了。不断的去更新当前区间的最远下标,如果当前遍历的下标和right下标一样,说明找到了分割点,这就是我们可以划分的一个字符串片段,这个字符串片段里的所有字符都只出现在这个片段里。都属于那种看起来好复杂,

2024-11-29 20:44:45 1037

原创 Day29 贪心算法 part03

第三种是20,这时候就要用到贪心算法了,我们要先使用10+5的组合,因为5元更加灵活,如果前面一种不行,然后再判断 5x3的组合。如果sum为负数,更新为0后,加上下一个值还是负数,那就会再次更新起点。5.总的来说,这道题坚持的原则就是出现sum为负数,说明[0, i]区间都不能作为起始位置,因为这个区间选择任何一个位置作为起点,到i这里都会断油,那么起始位置从i+1算起,再从0计算sum。经过前后两次遍历,取最大值之后,就可以从局部最优推出了全局最优,即:相邻的孩子中,评分高的孩子获得更多的糖果。

2024-11-28 20:33:12 1336

原创 Day28 贪心算法 part02

而不是碰到一个可以更新cover的机会就更新cover,应该是把当前cover遍历完,选择最大的cover更新一次,然后次数加 1。正确的应该是遍历到cover的最后一个元素,然后统计一次,再更新cover为下一步最大覆盖,如果更新后的cover可以覆盖掉最后一个元素,就break。其实不用纠结每步具体应该跳多少步,我们就去最大的步数,看最大的覆盖范围,不断的更新最大的覆盖范围,如果最后可以覆盖掉最后一个元素,那说明是可以跳到最后一个元素的。2.重点是分析每一天的情况,只要今天买,明天卖可以挣到钱就行。

2024-11-27 17:11:36 782

原创 Day 27 贪心算法 part01

而不是碰到元素小于0,就跳过这个元素,因为如果加上这个元素后,sum还是正数,就会 对后面的元素 起到增大总和的作用。也就是我们只需要在 这个坡度 摆动变化的时候,更新 prediff 就行,这样 prediff 在 单调区间有平坡的时候 就不会发生变化,造成我们的误判。这时候我们for循环就应该是遍历的饼干,让饼干风雨无阻的递增,如果饼干可以满足胃口要求了,胃口才指向下一个。这时候for循环就是遍历的胃口,让胃口风雨无阻的递减,而饼干就判断是否满足胃口的要求,如果满足胃口的要求了,饼干才递减指向下一个。

2024-11-26 16:53:37 906

原创 Day25 回溯算法 part04

3.注意used是不需要进行回溯的,因为used就是服务于本树层(集合)的,每个树层都会new一个新的used出来,这个是不会随着path进入到递归里面的。1.这道题的大体思路和回溯算法是一致的。因为 一刷 也不求大家能把这么难的问题解决,大家目前能了解一下题目的要求,了解一下解题思路,不求能直接写出代码,先大概熟悉一下这些题,二刷的时候,随着对回溯算法的深入理解,再去解决如下三题。2.写这道题必须明确给出了棋盘的宽度就是for循环的长度,递归的深度就是棋盘的高度,这样就可以套进回溯法的模板里了。

2024-11-25 21:31:22 640

原创 Day24 回溯算法part03

然后单层递归逻辑里面,我们是要判断[star i]这个区间得到的字符串是否符合要求,如果符合要求,那么我们就在i + 1加入一个点,然后继续下一层递归。2.首先这道题的终止条件,我们是借助了一个pointnum变量,表示加“.”的个数,如果个数为0了,代表已经切割好4段了,然后单独判断一下最后一段是否符合要求。大家之前做了 40.组合总和II 和 78.子集 ,本题就是这两道题目的结合,建议自己独立做一做,本题涉及的知识,之前都讲过,没有新内容。子集问题,就是收集树形结构中,每一个节点的结果。

2024-11-22 21:24:38 1035

原创 Day 23 回溯算法part02

难点有几个,一个是切割问题怎么抽象为组合问题,我们可以理解一段区间[starindex, i]( 或者[starindex, i+1))的字符串为一个元素。如果写成startindex,那所有集合的遍历都是从头开始,比如说【1,2】,到2的时候会输出【2,1】这样的结果就重复了。比如[1,1,2]和[1,2,1]。4.怎么把这道题理解为组合问题是关键,我的理解就是把区间[starindex, i]的字符串理解为一个元素,然后判断元素是否符合要求,再加入到path里面,这样path可以直接放进结果集里面。

2024-11-21 20:30:44 766

原创 Day22 回溯算法part01

第一种简洁的方法认为递归函数k,n,starindex都是动态变化的,我们添加了一个元素之和,下一次递归应该就是寻找k-1个数,然后它们的和为n-i,starindex + 1;第三种方法和第一种方法其实都是一样的,只是如果我们把n -= i单独写出来,相当于给n重新赋值,那我们就需要显示的写出回溯操作,把n加回去,不加回去的话,该层的递归会影响其他层的结果。剪枝版本1是认为递归函数是返回范围 [starindex, n] 中所有可能的 k 个数的组合,当k == 0的时候退出,我们认为k是一个变量。

2024-11-20 20:49:03 580

原创 Day 21 二叉树part08

我们只要明确递归函数是使用[left,right)范围的数组来构造二叉树,并返回新树的节点。主要是因为碰到要删除的节点,它的左节点或者右节点可能还有我们需要修剪得地方,所以需要调用递归函数来修剪,然后返回修剪之后的节点。因为这样的遍历顺序,我们相当于把这个二叉树转为递减的数组,这样我们只需要两个指针累加,得到的数值,就是比当前元素大的所有元素的数值之和。1.我们必须要明确递归函数在干什么(修剪树,使其在指定范围),它会返回什么(修剪之后的新节点),那么我们在递归函数里面再调用递归函数的时候,就不会出错了。

2024-11-19 20:39:18 871

原创 Day20 二叉树part07

如果刚好就在q和p的值中间,那么这个节点就是最近的公共节点。这一点是破题的关键!我们只需要root == null,向上返回新的节点,那么这个新的节点会自动找到叶子节点,并且知道挂在叶子节点的哪一边。4.第二种方法是适用于普通二叉树的使用交换的操作,目标节点在整个递归里面是会被找到两次第一次被找到,就和右子树的最左边的节点交换(因为目标节点和右子树的最左边的节点在排序上面是紧紧挨在一起的)。1.这道题需要明确的思路是我们碰到要删除的节点,应该返回他的下一个节点,上一层递归函数自然会接住这个返回的节点。

2024-11-19 11:34:49 814

原创 Day 18 二叉树part06

这种以pre元素为思考核心的方法就很容易出错,因为我们的退出条件是root == null,也就是说当root == null的时候就直接退出来,这样我们是无法保存到最后一个元素的。= root.val这里pre.val的前面就对pre == null考虑,也不是非要把pre == null这种情况给过滤掉,我们有时候可以一起考虑。5.在回溯的过程中,必然要遍历整棵二叉树,即使已经找到结果了,依然要把其他节点遍历完,因为要使用递归函数的返回值(也就是代码中的left和right)做逻辑判断。

2024-11-18 21:12:57 754

原创 Day17 二叉树 part05

单层递归的逻辑就是如果root.val > val,搜索左子树,如果root.val < val,就搜索右子树,最后如果都没有搜索到,就返回NULL。这个变量可以是一个节点,也可以是一个很小的数值。1.这道题就可以不使用HashMap了,因为使用HashMap也是需要每次遍历都new一个新的出来,因为我们使用集合找最大的元素,应该是新的范围区间里面生成的HashMap。4.中序遍历迭代法的逻辑就是先一路往左,然后左为null了,开始处理中间节点,把中间节点pop出来,然后再把指针指向右边。

2024-11-18 11:38:53 823

空空如也

空空如也

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

TA关注的人

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