前置知识
参考前文
参考文章:
LeetCode刷题笔记【9】:二叉树专题-1(分别用递归遍历、迭代遍历、标记遍历实现前、中、后序遍历)
LeetCode刷题笔记【10】:二叉树专题-2(二叉树的层序遍历、翻转二叉树、对称二叉树)
LeetCode刷题笔记【10.5】:二叉树专题-2.5(二叉树的层序遍历 - 10道题)
LeetCode刷题笔记【11】:二叉树专题-3(二叉树的最大深度、二叉树的最小深度、完全二叉树的节点个数)
110.平衡二叉树
题目描述
LeetCode链接:https://leetcode.cn/problems/balanced-binary-tree/description/
自顶向下法
设置一个函数depth
用于求当前节点的高度;
主函数isBalanced
深度遍历整个树, 对每个节点都用depth
检查其左右子树的高度是否符合要求.
class Solution {
public:
int depth(TreeNode* node){
if(node==nullptr)
return 0;
return max(depth(node->left), depth(node->right)) + 1;
}
bool isBalanced(TreeNode* root) {
if(root==nullptr) return true;
if( abs(depth(root->left) - depth(root->right)) <= 1)
return isBalanced(root->left)&&isBalanced(root->right);
return false;
}
};
自底向上法
上述方法也可以实现, 但整个过程是"自顶向下"的, 悲观情况下对每个节点都需要调用多遍depth
函数
如果是自底向上的, 对每个节点就只需要调用一次depth
class Solution {
public:
int depth(TreeNode* node){
if(node==nullptr)
return 0;
int leftDepth = depth(node->left);
int rightDepth = depth(node->right);
if(leftDepth==-1 || rightDepth==-1 || abs(leftDepth-rightDepth)>1)
return -1;
return max(leftDepth, rightDepth)+1;
}
bool isBalanced(TreeNode* root) {
return depth(root)!=-1;
}
};
最好瞅一眼LeetCode题解中的动态过程, 感受更深.
257. 二叉树的所有路径
题目描述
LeetCode链接:https://leetcode.cn/problems/binary-tree-paths/description/
解题思路
思路: 递归实现, 递归过程中维护一个string
递归到叶子节点的时候将string
加入vector<string> ans
代码
class Solution {
private:
vector<string> ans;
public:
void helper(TreeNode* node, string str){
str += to_string(node->val);
if(node->left==nullptr && node->right==nullptr){
ans.push_back(str);
return;
}else{
str += "->";
if(node->left) helper(node->left, str);
if(node->right) helper(node->right, str);
}
return;
}
vector<string> binaryTreePaths(TreeNode* root) {
if(root==nullptr)
return ans;
string str;
helper(root, str);
return ans;
}
};
404.左叶子之和
题目描述
LeetCode链接:https://leetcode.cn/problems/sum-of-left-leaves/description/
解题思路
进行深度优先遍历, 在过程中通过函数传参, 记录当前节点是左节点还是右节点
如果当前节点是叶子节点, 就检查是否是左节点, 左节点就加入ans
代码
class Solution {
private:
int ans=0;
public:
void helper(TreeNode* root, bool isLeft){
if(root==nullptr)
return;
if(root->left==nullptr && root->right==nullptr){// 如果是叶子节点
if(isLeft)// 并且还是一个左节点
ans += root->val;//计入ans
return;
}
if(root->left) helper(root->left, true);// 检查左子树
if(root->right) helper(root->right, false);// 检查右子树
return;
}
int sumOfLeftLeaves(TreeNode* root) {
helper(root, false);
return ans;
}
};
ps: 这里贴一下LeetCode官方给的题解吧, 思路是一样的.
感觉它写的很简洁, 或许执行起来会比我更快, 但是个人认为可读性不是很直观(比起我的直接传参);
class Solution {
public:
bool isLeafNode(TreeNode* node) {
return !node->left && !node->right;
}
int dfs(TreeNode* node) {
int ans = 0;
if (node->left) {
ans += isLeafNode(node->left) ? node->left->val : dfs(node->left);
}
if (node->right && !isLeafNode(node->right)) {
ans += dfs(node->right);
}
return ans;
}
int sumOfLeftLeaves(TreeNode* root) {
return root ? dfs(root) : 0;
}
};
作者:力扣官方题解
链接:https://leetcode.cn/problems/sum-of-left-leaves/solutions/419103/zuo-xie-zi-zhi-he-by-leetcode-solution/
来源:力扣(LeetCode)
总结
二叉树的题目普遍都有递归法和迭代法, 目前时间有限, 就先掌握递归法吧;
如果当天有时间精力, 或许可以折腾一下迭代法.
并且在使用递归的时候, 需要有意识地思考这个递归放出去了以后, 其内部执行过程是怎样的, 从而计算其时间复杂度.
至于递归的终点(结束点)等内容就是基础了.