文档讲解:代码随想录
视频讲解: 后序遍历求高度,高度判断是否平衡 | LeetCode:110.平衡二叉树
状态
左右子树的高度差不大于1,高度就采用后序遍历,同样使用递归的解法
class Solution {
public:
int IsAVL(TreeNode* root)
{
//终止条件
if(root == nullptr) return 0;
//后序遍历
//左节点
int left = IsAVL(root->left);
//如果得到-1的返回说明其子树中已经不满足,则直接返回-1
if(left == -1) return -1;
//右节点
int right = IsAVL(root->right);
if(right == -1) return -1;
//单层递归
//判断左右子树的高度差
if(abs(left-right) > 1)
{
return -1;
}
return 1+max(left,right);
}
public:
bool isBalanced(TreeNode* root) {
int res = IsAVL(root);
if(res == -1) return false;
return true;
}
};
利用层序遍历的迭代法:对每个节点进行层序遍历那么求得的就是以该节点为根节点的子树深度,同样也是高度。所以我们可以先定义一个求取深度的函数,然后同样利用层序遍历,对每个节点的左右子节点调用这个函数,然后来比较深度差值。
class Solution {
public:
int GetDep(TreeNode* cur)
{
queue treeque;
if(cur) treeque.push(cur);
int dep = 0;
while(!treeque.empty())
{
int tempsize = treeque.size();
for(int i = 0;ileft) treeque.push(temp->left);
if(temp->right) treeque.push(temp->right);
}
dep++;
}
return dep;
}
public:
bool isBalanced(TreeNode* root) {
queue treeque;
if(root) treeque.push(root);
while(!treeque .empty())
{
int tempsize = treeque.size();
for(int i=0;ileft);
int right = GetDep(cur->right);
if(abs(left-right) > 1)
{
return false;
}
treeque.pop();
if(cur->left) treeque.push(cur->left);
if(cur->right) treeque.push(cur->right);
}
}
return true;
}
};
文档讲解:代码随想录
视频讲解: 递归中带着回溯,你感受到了没?| LeetCode:257. 二叉树的所有路径
状态:×
从根节点开始到一个叶子节点的路径,采用前序遍历,当寻找到一条路径,还需要回退到上一个岔路口,选择另一条路进行遍历找到其他的路径,直到所找到的出口是最右边的叶子节点。
递归的三个要素
if (cur->left) {
traversal(cur->left, path, result);
path.pop_back(); // 回溯
}
if (cur->right) {
traversal(cur->right, path, result);
path.pop_back(); // 回溯
}
具体代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void GetPath(TreeNode* root, vector path, vector& res)
{
//中节点操作,先操作中节点,是为了叶子节点成为中节点是的加入path
path.push_back(root->val);
if(root->left == nullptr && root->right == nullptr)
{
string temp;
for(int i=0;i";
}
temp += to_string(path[path.size()-1]);
res.push_back(temp);
return ;
}
//递归左右,回溯
if(root->left)
{
GetPath(root->left,path,res);
//回溯到父节点 即岔路口
//path.pop_back();
}
if(root->right)
{
GetPath(root->right,path,res);
//path.pop_back();
}
}
public:
vector binaryTreePaths(TreeNode* root) {
vector temp;
vector res;
GetPath(root, temp, res);
return res;
}
};
回溯的目的主要要是保证当前节点的数组统计保持不变,这样在向回递归时,可以保持在节点处,所以如果对于传入函数的参数是值传入,那么其实就可以不需要使用回溯。因为对path的修改只是对临时变量的修改并不会改变函数外部的path,相当于用语法特性来完成了回溯。如果是按指针或者引用传递,那么就会对函数外部的path修改为了保持当前节点的path不变,需要手动回溯
文档讲解:代码随想录
视频讲解: 二叉树的题目中,总有一些规则让你找不到北 | LeetCode:404.左叶子之和
状态:
递归三要素
class Solution {
void GetLeft(TreeNode* root, int& sum)
{
if(root == nullptr) return ;
//对左节点的递归
if(root->left)
{
GetLeft(root->left,sum);
}
//对右节点的递归
if(root->right)
{
GetLeft(root->right,sum);
}
//对中节点的计算
if(root->left !=nullptr && root->left->left == nullptr && root->left->right == nullptr)
{
sum += root->left->val;
}
}
public:
int sumOfLeftLeaves(TreeNode* root) {
int sum = 0;
GetLeft(root,sum);
return sum;
}
};
采用的是左右中的顺序
采用层序遍历
对弹出的节点判断其是否有左叶子节点,如果是就加入
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
queue treeque;
if(root) treeque.push(root);
int sum = 0;
while(!treeque.empty())
{
int tempsize = treeque.size();
for(int i=0;ileft != nullptr && cur->left->left == nullptr && cur->left->right == nullptr)
{
sum += cur->left->val;
}
if(cur->left) treeque.push(cur->left);
if(cur->right) treeque.push(cur->right);
}
}
return sum;
}
};