mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-08 00:43:04 +08:00
Update
This commit is contained in:
@ -107,6 +107,7 @@
|
|||||||
* [二叉树:以为使用了递归,其实还隐藏着回溯](https://mp.weixin.qq.com/s/ivLkHzWdhjQQD1rQWe6zWA)
|
* [二叉树:以为使用了递归,其实还隐藏着回溯](https://mp.weixin.qq.com/s/ivLkHzWdhjQQD1rQWe6zWA)
|
||||||
* [二叉树:做了这么多题目了,我的左叶子之和是多少?](https://mp.weixin.qq.com/s/gBAgmmFielojU5Wx3wqFTA)
|
* [二叉树:做了这么多题目了,我的左叶子之和是多少?](https://mp.weixin.qq.com/s/gBAgmmFielojU5Wx3wqFTA)
|
||||||
* [二叉树:我的左下角的值是多少?](https://mp.weixin.qq.com/s/MH2gbLvzQ91jHPKqiub0Nw)
|
* [二叉树:我的左下角的值是多少?](https://mp.weixin.qq.com/s/MH2gbLvzQ91jHPKqiub0Nw)
|
||||||
|
* [二叉树:构造二叉树登场!](https://mp.weixin.qq.com/s/7r66ap2s-shvVvlZxo59xg)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -264,6 +265,7 @@
|
|||||||
|[0116.填充每个节点的下一个右侧节点指针](https://github.com/youngyangyang04/leetcode/blob/master/problems/0116.填充每个节点的下一个右侧节点指针.md) |二叉树 |中等|**广度优先搜索**|
|
|[0116.填充每个节点的下一个右侧节点指针](https://github.com/youngyangyang04/leetcode/blob/master/problems/0116.填充每个节点的下一个右侧节点指针.md) |二叉树 |中等|**广度优先搜索**|
|
||||||
|[0117.填充每个节点的下一个右侧节点指针II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0117.填充每个节点的下一个右侧节点指针II.md) |二叉树 |中等|**广度优先搜索**|
|
|[0117.填充每个节点的下一个右侧节点指针II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0117.填充每个节点的下一个右侧节点指针II.md) |二叉树 |中等|**广度优先搜索**|
|
||||||
|[0131.分割回文串](https://github.com/youngyangyang04/leetcode/blob/master/problems/0131.分割回文串.md) |回溯 |中等|**回溯**|
|
|[0131.分割回文串](https://github.com/youngyangyang04/leetcode/blob/master/problems/0131.分割回文串.md) |回溯 |中等|**回溯**|
|
||||||
|
|[0141.环形链表](https://github.com/youngyangyang04/leetcode/blob/master/problems/0141.环形链表.md) |链表 |简单|**快慢指针/双指针**|
|
||||||
|[0142.环形链表II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0142.环形链表II.md) |链表 |中等|**快慢指针/双指针**|
|
|[0142.环形链表II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0142.环形链表II.md) |链表 |中等|**快慢指针/双指针**|
|
||||||
|[0144.二叉树的前序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0144.二叉树的前序遍历.md) |树 |中等|**递归** **迭代/栈**|
|
|[0144.二叉树的前序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0144.二叉树的前序遍历.md) |树 |中等|**递归** **迭代/栈**|
|
||||||
|[0145.二叉树的后序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0145.二叉树的后序遍历.md) |树 |困难|**递归** **迭代/栈**|
|
|[0145.二叉树的后序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0145.二叉树的后序遍历.md) |树 |困难|**递归** **迭代/栈**|
|
||||||
|
BIN
pics/42.接雨水1.png
Normal file
BIN
pics/42.接雨水1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 84 KiB |
BIN
pics/42.接雨水2.png
Normal file
BIN
pics/42.接雨水2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 84 KiB |
BIN
pics/42.接雨水3.png
Normal file
BIN
pics/42.接雨水3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 46 KiB |
BIN
pics/654.最大二叉树.png
Normal file
BIN
pics/654.最大二叉树.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
@ -97,4 +97,8 @@ public:
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# 拓展
|
||||||
|
|
||||||
|
请问为什么 getCombinations(const string& digits, int index, const string& s)函数里的string& s 前要加const,不加的报错
|
||||||
|
|
||||||
> 更多算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
> 更多算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
||||||
|
@ -6,41 +6,103 @@
|
|||||||
// 找左面最大的, 找右边最大的,找左右边际的时候容易迷糊。我已开始还找左大于右的。 (还不够)
|
// 找左面最大的, 找右边最大的,找左右边际的时候容易迷糊。我已开始还找左大于右的。 (还不够)
|
||||||
// 每次记录单条,不要记录整个面积
|
// 每次记录单条,不要记录整个面积
|
||||||
|
|
||||||
# C++代码
|
## 暴力解法
|
||||||
|
|
||||||
|
这道题目暴力解法并不简单,我们来看一下思路。
|
||||||
|
|
||||||
|
首先要明确,要按照行来计算,还是按照列来计算。如图所示:
|
||||||
|
|
||||||
|
<img src='../pics/42.接雨水2.png' width=600> </img></div>
|
||||||
|
|
||||||
|
<img src='../pics/42.接雨水1.png' width=600> </img></div>
|
||||||
|
|
||||||
|
一些同学在实现暴力解法的时候,很容易一会按照行来计算一会按照列来计算,这样就会越写越乱。
|
||||||
|
|
||||||
|
我个人倾向于按照列来计算,比较容易理解,接下来看一下按照列如何计算。
|
||||||
|
|
||||||
|
首先,**如果按照列来计算的话,宽度一定是1了,我们再把每一列的雨水的高度求出来就可以了。**
|
||||||
|
|
||||||
|
可以看出每一列雨水的高度,取决于,该列 左侧最高的柱子和右侧最高的柱子中最矮的那个柱子的高度。
|
||||||
|
|
||||||
|
这句话可以有点绕,来举一个理解,例如求列4的雨水高度,如图:
|
||||||
|
|
||||||
|
<img src='../pics/42.接雨水3.png' width=600> </img></div>
|
||||||
|
|
||||||
|
列4 左侧最高的柱子是列3,高度为2(以下用lHeight表示)。
|
||||||
|
|
||||||
|
列4 右侧最高的柱子是列7,高度为3(以下用rHeight表示)。
|
||||||
|
|
||||||
|
列4 柱子的高度为1(以下用height表示)
|
||||||
|
|
||||||
|
那么列4的雨水高度为 列3和列7的高度最小值减列4高度,即: min(lHeight, rHeight) - height。
|
||||||
|
|
||||||
|
列4的雨水高度求出来了,宽度为1,相乘就是列4的雨水体积了。
|
||||||
|
|
||||||
|
此时求出了列4的雨水体积。
|
||||||
|
|
||||||
|
一样的方法,只要从头遍历一遍所有的列,然后求出每一列雨水的体积,相加之后就是总雨水的体积了。
|
||||||
|
|
||||||
|
首先从头遍历所有的列,并且**要注意第一个柱子和最后一个柱子不接雨水**,代码如下:
|
||||||
|
```
|
||||||
|
for (int i = 0; i < height.size(); i++) {
|
||||||
|
// 第一个柱子和最后一个柱子不接雨水
|
||||||
|
if (i == 0 || i == height.size() - 1) continue;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
在for循环中求左右两边最高柱子,代码如下:
|
||||||
|
|
||||||
|
```
|
||||||
|
int rHeight = height[i]; // 记录右边柱子的最高高度
|
||||||
|
int lHeight = height[i]; // 记录左边柱子的最高高度
|
||||||
|
for (int r = i + 1; r < height.size(); r++) {
|
||||||
|
if (height[r] > rHeight) rHeight = height[r];
|
||||||
|
}
|
||||||
|
for (int l = i - 1; l >= 0; l--) {
|
||||||
|
if (height[l] > lHeight) lHeight = height[l];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
最后,计算该列的雨水高度,代码如下:
|
||||||
|
|
||||||
|
```
|
||||||
|
int h = min(lHeight, rHeight) - height[i];
|
||||||
|
if (h > 0) sum += h; // 注意只有h大于零的时候,在统计到总和中
|
||||||
|
```
|
||||||
|
|
||||||
|
整体代码如下:
|
||||||
|
|
||||||
按照列来
|
|
||||||
```
|
```
|
||||||
class Solution {
|
class Solution {
|
||||||
public:
|
public:
|
||||||
int trap(vector<int>& height) {
|
int trap(vector<int>& height) {
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
// for (int i = 0; i < height.size(); i++) {
|
|
||||||
// cout << height[i] << " ";
|
|
||||||
// }
|
|
||||||
// cout << endl;
|
|
||||||
for (int i = 0; i < height.size(); i++) {
|
for (int i = 0; i < height.size(); i++) {
|
||||||
|
// 第一个柱子和最后一个柱子不接雨水
|
||||||
if (i == 0 || i == height.size() - 1) continue;
|
if (i == 0 || i == height.size() - 1) continue;
|
||||||
|
|
||||||
int lIndex, rIndex;
|
int rHeight = height[i]; // 记录右边柱子的最高高度
|
||||||
int rValue = height[i];
|
int lHeight = height[i]; // 记录左边柱子的最高高度
|
||||||
int lValue = height[i];
|
|
||||||
for (int r = i + 1; r < height.size(); r++) {
|
for (int r = i + 1; r < height.size(); r++) {
|
||||||
if (height[r] > rValue) {
|
if (height[r] > rHeight) rHeight = height[r];
|
||||||
rValue = height[r];
|
|
||||||
rIndex = r;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (int l = i - 1; l >= 0; l--) {
|
for (int l = i - 1; l >= 0; l--) {
|
||||||
if (height[l] > lValue) {
|
if (height[l] > lHeight) lHeight = height[l];
|
||||||
lValue = height[l];
|
|
||||||
lIndex = l;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
int h = min(lValue, rValue) - height[i];
|
int h = min(lHeight, rHeight) - height[i];
|
||||||
// 我为啥要算 (rIndex - lIndex + 1);就是按照行 按照列 区分不清啊
|
|
||||||
if (h > 0) sum += h;
|
if (h > 0) sum += h;
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
因为每次遍历列的时候,还要向两边寻找最高的列,所以时间复杂度为O(n^2)。
|
||||||
|
空间复杂度为O(1)。
|
||||||
|
|
||||||
|
|
||||||
|
# 单调栈
|
||||||
|
|
||||||
|
单调栈究竟如何做呢,得画一个图,不太好理解
|
||||||
|
|
||||||
|
按照列来算的,遇到相同的怎么办。
|
||||||
|
@ -19,6 +19,11 @@ fast和slow各自再走一步, fast和slow就相遇了
|
|||||||
|
|
||||||
这是因为fast是走两步,slow是走一步,**其实相对于slow来说,fast是一个节点一个节点的靠近slow的**,所以fast一定可以和slow重合。
|
这是因为fast是走两步,slow是走一步,**其实相对于slow来说,fast是一个节点一个节点的靠近slow的**,所以fast一定可以和slow重合。
|
||||||
|
|
||||||
|
动画如下:
|
||||||
|
|
||||||
|
|
||||||
|
<img src='../video/141.环形链表.gif' width=600> </img></div>
|
||||||
|
|
||||||
|
|
||||||
## C++代码如下
|
## C++代码如下
|
||||||
|
|
||||||
|
@ -43,6 +43,11 @@ fast和slow各自再走一步, fast和slow就相遇了
|
|||||||
|
|
||||||
这是因为fast是走两步,slow是走一步,**其实相对于slow来说,fast是一个节点一个节点的靠近slow的**,所以fast一定可以和slow重合。
|
这是因为fast是走两步,slow是走一步,**其实相对于slow来说,fast是一个节点一个节点的靠近slow的**,所以fast一定可以和slow重合。
|
||||||
|
|
||||||
|
动画如下:
|
||||||
|
|
||||||
|
|
||||||
|
<video src='../video/142.环形链表II1.mp4' controls='controls' width='640' height='320' autoplay='autoplay'> Your browser does not support the video tag.</video></div>
|
||||||
|
|
||||||
|
|
||||||
## 如果有环,如何找到这个环的入口
|
## 如果有环,如何找到这个环的入口
|
||||||
|
|
||||||
@ -83,6 +88,11 @@ fast指针走过的节点数:` x + y + n (y + z)`,n为fast指针在环内走
|
|||||||
|
|
||||||
让index1和index2同时移动,每次移动一个节点, 那么他们相遇的地方就是 环形入口的节点。
|
让index1和index2同时移动,每次移动一个节点, 那么他们相遇的地方就是 环形入口的节点。
|
||||||
|
|
||||||
|
动画如下:
|
||||||
|
|
||||||
|
<video src='../video/142.环形链表II.mp4' controls='controls' width='640' height='320' autoplay='autoplay'> Your browser does not support the video tag.</video></div>
|
||||||
|
|
||||||
|
|
||||||
那么 n如果大于1是什么情况呢,就是fast指针在环形转n圈之后才遇到 slow指针。
|
那么 n如果大于1是什么情况呢,就是fast指针在环形转n圈之后才遇到 slow指针。
|
||||||
|
|
||||||
其实这种情况和n为1的时候 效果是一样的,一样可以通过这个方法找到 环形的入口节点,只不过,index1 指针在环里 多转了(n-1)圈,然后再遇到index2,相遇点依然是环形的入口节点。
|
其实这种情况和n为1的时候 效果是一样的,一样可以通过这个方法找到 环形的入口节点,只不过,index1 指针在环里 多转了(n-1)圈,然后再遇到index2,相遇点依然是环形的入口节点。
|
||||||
|
@ -1,19 +1,35 @@
|
|||||||
## 题目地址
|
## 题目地址
|
||||||
https://leetcode-cn.com/problems/maximum-binary-tree/
|
https://leetcode-cn.com/problems/maximum-binary-tree/
|
||||||
|
|
||||||
|
> 用数组构建二叉树都是一样的套路
|
||||||
|
|
||||||
|
# 654.最大二叉树
|
||||||
|
|
||||||
|
给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下:
|
||||||
|
|
||||||
|
* 二叉树的根是数组中的最大元素。
|
||||||
|
* 左子树是通过数组中最大值左边部分构造出的最大二叉树。
|
||||||
|
* 右子树是通过数组中最大值右边部分构造出的最大二叉树。
|
||||||
|
|
||||||
|
通过给定的数组构建最大二叉树,并且输出这个树的根节点。
|
||||||
|
|
||||||
|
示例 :
|
||||||
|
|
||||||
|
<img src='../pics/654.最大二叉树.png' width=600> </img></div>
|
||||||
|
|
||||||
|
提示:
|
||||||
|
|
||||||
|
给定的数组的大小在 [1, 1000] 之间。
|
||||||
|
|
||||||
## 思路
|
## 思路
|
||||||
|
|
||||||
最大二叉树的构建过程如下:
|
最大二叉树的构建过程如下:
|
||||||
|
|
||||||
<video src='../video/654.最大二叉树.mp4' controls='controls' width='640' height='320' autoplay='autoplay'> Your browser does not support the video tag.</video></div>
|
<img src='../video/654.最大二叉树.gif' width=600> </img></div>
|
||||||
|
|
||||||
典型的递归问题,依然按照递归三部曲来分析:
|
构造树一般采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树。
|
||||||
|
|
||||||
* 确定递归函数的参数和返回值
|
* 确定递归函数的参数和返回值
|
||||||
* 确定终止条件
|
|
||||||
* 确定单层递归的逻辑
|
|
||||||
|
|
||||||
### 确定递归函数的参数和返回值
|
|
||||||
|
|
||||||
参数就是传入的是存放元素的数组,返回该数组构造的二叉树的头结点,返回类型是指向节点的指针。
|
参数就是传入的是存放元素的数组,返回该数组构造的二叉树的头结点,返回类型是指向节点的指针。
|
||||||
|
|
||||||
@ -23,9 +39,11 @@ https://leetcode-cn.com/problems/maximum-binary-tree/
|
|||||||
TreeNode* constructMaximumBinaryTree(vector<int>& nums)
|
TreeNode* constructMaximumBinaryTree(vector<int>& nums)
|
||||||
|
|
||||||
```
|
```
|
||||||
### 确定终止条件
|
* 确定终止条件
|
||||||
|
|
||||||
题目中说了输入的数组大小一定是大于等于1的,所以我们不用考虑小于1的情况,那么当递归遍历的时候,如果传入的数组大小为1,说明遍历到了具体节点了,那么应该定义一个新的节点,并把这个数组的数值赋给新的节点,然后返回这个节点。 这表示一个数组大小是1的时候,构造了一个新的节点,并返回。
|
题目中说了输入的数组大小一定是大于等于1的,所以我们不用考虑小于1的情况,那么当递归遍历的时候,如果传入的数组大小为1,说明遍历到了叶子节点了。
|
||||||
|
|
||||||
|
那么应该定义一个新的节点,并把这个数组的数值赋给新的节点,然后返回这个节点。 这表示一个数组大小是1的时候,构造了一个新的节点,并返回。
|
||||||
|
|
||||||
代码如下:
|
代码如下:
|
||||||
|
|
||||||
@ -36,11 +54,12 @@ if (nums.size() == 1) {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
### 确定单层递归的逻辑
|
|
||||||
|
* 确定单层递归的逻辑
|
||||||
|
|
||||||
这里有三步工作
|
这里有三步工作
|
||||||
|
|
||||||
1. 先要找到数组中最大的值和对应的下表, 最大的值就是根节点
|
1. 先要找到数组中最大的值和对应的下表, 最大的值构造根节点,下表用来下一步分割数组。
|
||||||
|
|
||||||
代码如下:
|
代码如下:
|
||||||
```
|
```
|
||||||
@ -82,8 +101,6 @@ if (maxValueIndex < (nums.size() - 1)) {
|
|||||||
```
|
```
|
||||||
这样我们就分析完了,整体代码如下:(详细注释)
|
这样我们就分析完了,整体代码如下:(详细注释)
|
||||||
|
|
||||||
## C++代码
|
|
||||||
|
|
||||||
```
|
```
|
||||||
class Solution {
|
class Solution {
|
||||||
public:
|
public:
|
||||||
@ -105,7 +122,7 @@ public:
|
|||||||
node->val = maxValue;
|
node->val = maxValue;
|
||||||
// 最大值所在的下表左区间 构造左子树
|
// 最大值所在的下表左区间 构造左子树
|
||||||
if (maxValueIndex > 0) {
|
if (maxValueIndex > 0) {
|
||||||
vector<int> newVec(nums.begin(), nums.begin() + maxValueIndex);
|
vector<int> newVec(nums.begin(), nums.begin() + maxValueIndex);
|
||||||
node->left = constructMaximumBinaryTree(newVec);
|
node->left = constructMaximumBinaryTree(newVec);
|
||||||
}
|
}
|
||||||
// 最大值所在的下表右区间 构造右子树
|
// 最大值所在的下表右区间 构造右子树
|
||||||
@ -117,4 +134,86 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
以上代码比较冗余,效率也不高,每次还要切割的时候每次都要定义新的vector(也就是数组),但逻辑比较清晰。
|
||||||
|
|
||||||
|
和文章[二叉树:构造二叉树登场!](https://mp.weixin.qq.com/s/7r66ap2s-shvVvlZxo59xg)中一样的优化思路,就是每次分隔不用定义新的数组,而是通过下表索引直接在原数组上操作。
|
||||||
|
|
||||||
|
优化后代码如下:
|
||||||
|
|
||||||
|
```
|
||||||
|
class Solution {
|
||||||
|
private:
|
||||||
|
// 在左闭右开区间[left, right),构造二叉树
|
||||||
|
TreeNode* traversal(vector<int>& nums, int left, int right) {
|
||||||
|
if (left >= right) return nullptr;
|
||||||
|
|
||||||
|
// 分割点下表:maxValueIndex
|
||||||
|
int maxValueIndex = left;
|
||||||
|
for (int i = left + 1; i < right; ++i) {
|
||||||
|
if (nums[i] > nums[maxValueIndex]) maxValueIndex = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode* root = new TreeNode(nums[maxValueIndex]);
|
||||||
|
|
||||||
|
// 左闭右开:[left, maxValueIndex)
|
||||||
|
root->left = traversal(nums, left, maxValueIndex);
|
||||||
|
|
||||||
|
// 左闭右开:[maxValueIndex + 1, right)
|
||||||
|
root->right = traversal(nums, maxValueIndex + 1, right);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
|
||||||
|
return traversal(nums, 0, nums.size());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
# 拓展
|
||||||
|
|
||||||
|
可以发现上面的代码看上去简洁一些,**主要是因为第二版其实是允许空节点进入递归,所以不用在递归的时候加判断节点是否为空**
|
||||||
|
|
||||||
|
第一版递归过程:(加了if判断,为了不让空节点进入递归)
|
||||||
|
```
|
||||||
|
|
||||||
|
if (maxValueIndex > 0) { // 这里加了判断是为了不让空节点进入递归
|
||||||
|
vector<int> newVec(nums.begin(), nums.begin() + maxValueIndex);
|
||||||
|
node->left = constructMaximumBinaryTree(newVec);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxValueIndex < (nums.size() - 1)) { // 这里加了判断是为了不让空节点进入递归
|
||||||
|
vector<int> newVec(nums.begin() + maxValueIndex + 1, nums.end());
|
||||||
|
node->right = constructMaximumBinaryTree(newVec);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
第二版递归过程: (如下代码就没有加if判断)
|
||||||
|
|
||||||
|
```
|
||||||
|
root->left = traversal(nums, left, maxValueIndex);
|
||||||
|
|
||||||
|
root->right = traversal(nums, maxValueIndex + 1, right);
|
||||||
|
```
|
||||||
|
|
||||||
|
第二版代码是允许空节点进入递归,所以没有加if判断,当然终止条件也要有相应的改变。
|
||||||
|
|
||||||
|
第一版终止条件,是遇到叶子节点就终止,因为空节点不会进入递归。
|
||||||
|
|
||||||
|
第二版相应的终止条件,是遇到空节点,也就是数组区间为0,就终止了。
|
||||||
|
|
||||||
|
|
||||||
|
# 总结
|
||||||
|
|
||||||
|
这道题目其实和 [二叉树:构造二叉树登场!](https://mp.weixin.qq.com/s/7r66ap2s-shvVvlZxo59xg) 是一个思路,比[二叉树:构造二叉树登场!](https://mp.weixin.qq.com/s/7r66ap2s-shvVvlZxo59xg) 还简单一些。
|
||||||
|
|
||||||
|
**注意类似用数组构造二叉树的题目,每次分隔尽量不要定义新的数组,而是通过下表索引直接在原数组上操作,这样可以节约时间和空间上的开销。**
|
||||||
|
|
||||||
|
一些同学也会疑惑,什么时候递归函数前面加if,什么时候不加if,这个问题我在最后也给出了解释。
|
||||||
|
|
||||||
|
其实就是不同代码风格的实现,**一般情况来说:如果让空节点(空指针)进入递归,就不加if,如果不让空节点进入递归,就加if限制一下, 终止条件也会相应的调整。**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
> 更多算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
> 更多算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
||||||
|
BIN
video/141.环形链表.gif
Normal file
BIN
video/141.环形链表.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 MiB |
BIN
video/141.环形链表.mp4
Normal file
BIN
video/141.环形链表.mp4
Normal file
Binary file not shown.
BIN
video/142.环形链表II.mp4
Normal file
BIN
video/142.环形链表II.mp4
Normal file
Binary file not shown.
BIN
video/142.环形链表II1.mp4
Normal file
BIN
video/142.环形链表II1.mp4
Normal file
Binary file not shown.
BIN
video/654.最大二叉树.gif
Normal file
BIN
video/654.最大二叉树.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 724 KiB |
Reference in New Issue
Block a user