110.平衡二叉树
力扣题目链接 题目描述: 给定一个二叉树,判断它是否是高度平衡的二叉树。 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
示例 1: 输入:root = [3,9,20,null,null,15,7] 输出:true
思路:
- 先明白一个概念,什么是二叉树高度和深度?
- 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数。
- 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数。
- 另外,一般求高度用后序遍历,而求深度用前序遍历。
- 递归法:判断左右子树的高度,然后求其差值,只要大于1,就不是平衡二叉树,小于1就返回其最大高度。
- 递归三部曲
- 确定函数参数和返回值:参数就是根节点、返回值是树的最大高度,当然一旦知道不是平衡二叉树可以返回-1,标记。
- 确定退出条件,
if (root == nullptr) return 0; - 单步处理逻辑,先判断左右子树返回值是不是-1,不是的话比较两子树高度之差,大于1返回-1,否则返回树的最大高度。
代码实现:
int get_high(TreeNode* root) {
if (root == nullptr) return 0;
int left_high = get_high(root->left);
if (left_high == - 1) return -1;
int right_high = get_high(root->right);
if (right_high == -1) return - 1;
if (abs(left_high - right_high) > 1) {
return -1;
}
return max(left_high, right_high) + 1;
}
bool isBalanced(TreeNode* root) {
if (root == nullptr) return true;
return get_high(root) == -1 ? false : true;
}
- 迭代法(比较繁琐,有思路就行):迭代法比较复杂,先写一个函数求左右子树的高度(后序遍历),然后遍历(哪种遍历方式都可以)二叉树节点判断每个节点是不是平衡二叉树。
257. 二叉树的所有路径
力扣题目链接 题目描述: 给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。 叶子节点 是指没有子节点的节点。
思路:
- 递归法:因为是根节点到所有叶子节点,那么可以采用前序遍历,递归三部曲,如下:
- 确定函数参数和返回值:函数参数首先是根节点、然后还需要一个results存储结果集,另外还需要一个数组或string来存储路径。由于我们没必要处理返回值,返回值为void。
- 函数退出条件:在碰到叶子节点时,说明形成一条完整的路径,直接放到results里退出即可。
- 单步处理逻辑:左右子节点非空时,分别递归左右子节点即可。
void traversal(TreeNode* root, string path, vector<string>& results) {
path += to_string(root->val);
if (!root->right && !root->left) {
results.push_back(path);
}
if(root->right) {
traversal(root->right, path + "->", results);
}
if(root->left) {
traversal(root->left, path + "->", results);
}
}
vector<string> binaryTreePaths(TreeNode* root) {
if(root == nullptr) {
return {};
}
string path;
vector<string> results;
traversal(root, path, results);
return results;
}
- 迭代法:
- 利用两个栈,一个栈用来处理(存路径),一个栈用来访问(存节点),同样采用前序遍历实现。碰到叶子节点就将路径存到结果集。
代码实现
vector<string> binaryTreePaths(TreeNode* root) {
if(root == nullptr) {
return {};
}
stack<TreeNode*> stk;
stk.push(root);
stack<string> stk1;
stk1.push(to_string(root->val));
vector<string> results;
while(!stk.empty()) {
TreeNode* cur = stk.top();
string path = stk1.top();
stk.pop(), stk1.pop();
if (!cur->left && !cur->right) {
results.push_back(path);
}
if (cur->left) {
stk.push(cur->left);
stk1.push(path + "->" + to_string(cur->left->val));
}
if (cur->right) {
stk.push(cur->right);
stk1.push(path + "->" + to_string(cur->right->val));
}
}
return results;
}
404.左叶子之和(这道题通过父节点判断子节点,和其他题有点差别)
力扣题目链接 题目描述: 给定二叉树的根节点 root ,返回所有左叶子之和。
思路:
- 因为要找左叶子节点,首先这个节点得是叶子节点(左右子树都为空),其次我们无法判断是左叶子还是右叶子,那么只能通过父节点来判断,明白这个就好做了。
- 递归法:本体递归逻辑就是后序遍历,找出左子树的左叶子之和,和右子树的左叶子之和,相加即可,然后通过父节点来找左叶子节点,那么直接上递归三部曲:
- 确定函数参数和返回值:参数为根节点,,返回值为sum
- 确定函数退出条件:当节点为空时,返回0(把左节点非空和右节点非空加到单步逻辑里,这个判断条件就可以不写了)
- 确定单步处理逻辑:当左节点不为空时,判断左节点是不是叶子节点,是的话加到
left_sum,不是的话,递归左右节点,最后返回return left_sum + right_sum;
代码实现:
int sumOfLeftLeaves(TreeNode* root) {
if (root == nullptr) return 0;
int left_sum = 0, right_sum = 0;
if (root->left && !root->left->left && !root->left->right) {
left_sum = root->left->val;
} else {
left_sum = sumOfLeftLeaves(root->left);
}
right_sum = sumOfLeftLeaves(root->right);
return left_sum + right_sum;
}
- 迭代法:直接前后序遍历或者层次遍历找每个节点的左叶子节点即可
//前序遍历
int sumOfLeftLeaves(TreeNode* root) {
if (root == nullptr) return 0;
stack<TreeNode*> stk;
stk.push(root);
int sum = 0;
while(!stk.empty()) {
TreeNode* cur = stk.top();
stk.pop();
if (cur->left && !cur->left->left && !cur->left->right) {
sum += cur->left->val;
}
if (cur->left) stk.push(cur->left);
if (cur->right) stk.push(cur->right);
}
return sum;
}