代码随想录【day 17 二叉树】| 110.平衡二叉树 257. 二叉树的所有路径 404.左叶子之和
LeetCode 110.平衡二叉树
题目链接:110.平衡二叉树
卡哥文解
视频讲解
- 题目描述: 给定一个二叉树,判断它是否是高度平衡的二叉树。
- 本题中,一棵高度平衡二叉树定义为:
- 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 。
解题思路
1、深度:根节点到任意一个节点的距离(从上往下:前序遍历)中左右 距离根节点的距离
高度:任意一个节点到叶子节点的距离(从下往上:后序遍历)左右中:把叶子节点的高度返回给父节点
2、任意一个节点左右子树的高度差超过1 - > 向上返回-1 -> 此树不是平衡二叉树
3、每次递归两件事:判断每个节点(以此为根节点)的左右子树高度 并且返回高度值或-1(-1用来标记不符合平衡树)
4、计算每个节点的高度:左右子树的高度取最大值(1+max(rightHeight,leftHeight)
)+本身高度(1
)
注意事项
1、使用层序遍历求深度,通过栈模拟的后序遍历找每一个节点的高度
代码实现1(后序遍历)
/**
* 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:
int getheight(TreeNode* node){
if(node==NULL)return 0;
int leftHeight = getheight(node->left);
if(leftHeight==-1)return -1;
int rightHeight = getheight(node->right);
if(rightHeight==-1)return -1;
if(abs(rightHeight-leftHeight)>1)return -1;
else{
return 1+max(leftHeight,rightHeight);// 以当前节点为根节点的树的最大高度
}
}
bool isBalanced(TreeNode* root) {
int result;
result = getheight(root);
if(result==-1)return false;
else return true;
}
};
代码实现2(迭代遍历)
/**
* 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:
int getheight(TreeNode* cur){
// stack<TreeNode*>st;
queue<TreeNode*>que;
if(cur != NULL)que.push(cur);
int depth = 0;
while(!que.empty()){
int size = que.size();
depth++;
TreeNode* node;
while(size--){
node = que.front();
que.pop();
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
}
}
return depth;
}
bool isBalanced(TreeNode* root) {
queue<TreeNode*>que;
if(root==NULL)return true;
que.push(root);
while(!que.empty()){
TreeNode* node=que.front();
que.pop();
if(abs(getheight(node->left)-getheight(node->right))>1)return false;
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
}
return true;
}
};
LeetCode 257. 二叉树的所有路径
题目链接:LeetCode257.二叉树的所有路径
卡哥文解
视频讲解
- 题目描述: 给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
- 叶子节点 是指没有子节点的节点。
解题思路(递归+回溯)
- 回溯 :使用vector结构方便做回溯
- 从根节点到叶子的路径,需要前序遍历让父节点指向孩子节点
- 单层递归逻辑:前序遍历:需要先处理中间节点,将路径上的节点放进path
实现难点
- 使用vector记录路径,把vector结构的path转为string格式,并且根据输出要求:数组改为字符串 元素之间加上 ->
- 输出需要包括叶子节点,终止条件:if(cur->left == NULL && cur->right==NULL)
代码实现(递归+回溯)
/**
* 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 traversal(TreeNode* cur, vector<int>&path, vector<string>& result){
path.push_back(cur->val);
// 判断到了叶子节点
if(cur->left==NULL && cur->right==NULL){
string sPath;
// 将结果转换为字符串并且加上->
for(int i=0;i<path.size()-1;i++){
sPath += to_string(path[i]);
sPath += "->";
}
sPath += to_string(path[path.size()-1]); // 最后一个字符后不用加 ->
result.push_back(sPath);
return;
}
if(cur->left){
traversal(cur->left,path,result);
path.pop_back(); // 每一层递归里都要有一层回溯
}
if(cur->right){
traversal(cur->right,path,result);
path.pop_back();
}
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<string>result;
vector<int>path;
if(root==NULL)return result;
traversal(root,path,result);
return result;
}
};
LeetCode 404.左叶子之和
题目链接:LeetCode404.左叶子之和
卡哥文解
视频讲解
- 题目描述:给定二叉树的根节点 root ,返回所有左叶子之和。
解题思路
- 左叶子 ≠ 左侧节点,明确定义:节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点
- 判断当前节点是不是左叶子:通过节点的父节点来判断
- 只有当前遍历的节点是父节点,才能判断其子节点是不是左叶子。如果当前遍历的节点是叶子节点,那其左叶子必定为0
判断是否为左叶子节点的代码:
if(node->left !=NULL && node->left->left == NULL && node->left->right ==NULL){
左叶子节点处理
}
代码实现
/**
* 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:
int sumOfLeftLeaves(TreeNode* root) {
if(root==NULL)return 0;
if(root->left==NULL && root->right==NULL)return 0;
int leftValue = sumOfLeftLeaves(root->left); // 左
// 判断是否为左叶子
if(root->left!=NULL && root->left->left == NULL && root->left->right==NULL){
leftValue = root->left->val;
}
int rightValue = sumOfLeftLeaves(root->right);//右
int sum = leftValue + rightValue;
return sum;
}
};
day17总结复盘
1、后序遍历求的是高度,前序遍历求深度
2、真正解题时分不清解决问题时究竟用哪种遍历顺序
3、迭代法解题时分不清用栈还是队列
4、递归的解题思路:①判断递归函数的参数和返回值②确定终止条件③确定单层递归的逻辑