目录
①力扣2331. 计算布尔二叉树的值
解析代码
②力扣129. 求根节点到叶节点数字之和
解析代码
③力扣814. 二叉树剪枝
解析代码
④力扣98. 验证二叉搜索树
解析代码
⑤力扣230. 二叉搜索树中第K小的元素
解析代码
⑥力扣257. 二叉树的所有路径
解析代码
①力扣2331. 计算布尔二叉树的值
2331. 计算布尔二叉树的值
难度 简单
给你一棵 完整二叉树 的根,这棵树有以下特征:
-
叶子节点 要么值为
0
要么值为1
,其中0
表示False
,1
表示True
。 -
非叶子节点 要么值为
2
要么值为3
,其中2
表示逻辑或OR
,3
表示逻辑与AND
。
计算 一个节点的值方式如下:
- 如果节点是个叶子节点,那么节点的 值 为它本身,即
True
或者False
。 - 否则,计算 两个孩子的节点值,然后将该节点的运算符对两个孩子值进行 运算 。
返回根节点 root
的布尔运算值。
完整二叉树 是每个节点有 0
个或者 2
个孩子的二叉树。
叶子节点 是没有孩子的节点。
示例 1:
输入:root = [2,1,3,null,null,0,1] 输出:true 解释:上图展示了计算过程。 AND 与运算节点的值为 False AND True = False 。 OR 运算节点的值为 True OR False = True 。 根节点的值为 True ,所以我们返回 true 。
示例 2:
输入:root = [0] 输出:false 解释:根节点是叶子节点,且值为 false,所以我们返回 false 。
提示:
- 树中节点数目在
[1, 1000]
之间。 0 <= Node.val <= 3
- 每个节点的孩子数为
0
或2
。 - 叶子节点的值为
0
或1
。 - 非叶子节点的值为
2
或3
。
/**
* 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:
bool evaluateTree(TreeNode* root) {
}
};
解析代码
通过题目拆分成子问题,使用递归:
计算当前结果就要知道左子树的结果和右子树的结果,遇到叶子结点返回。
/**
* 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:
bool evaluateTree(TreeNode* root) {
if(root->left == nullptr)
return root->val; // 0/1
bool left = evaluateTree(root->left);
bool right = evaluateTree(root->right);
return root->val == 2 ? (left || right) : (left && right); // 因为是bool所以可以用下面的逻辑与和或
// return root->val == 2 ? (left | right) : (left & right);
}
};
②力扣129. 求根节点到叶节点数字之和
129. 求根节点到叶节点数字之和
难度 中等
给你一个二叉树的根节点 root
,树中每个节点都存放有一个 0
到 9
之间的数字。
每条从根节点到叶节点的路径都代表一个数字:
- 例如,从根节点到叶节点的路径
1 -> 2 -> 3
表示数字123
。
计算从根节点到叶节点生成的 所有数字之和 。
叶节点 是指没有子节点的节点。
示例 1:
输入:root = [1,2,3] 输出:25 解释: 从根到叶子节点路径1->2
代表数字12
从根到叶子节点路径1->3
代表数字13
因此,数字总和 = 12 + 13 =25
示例 2:
输入:root = [4,9,0,5,1] 输出:1026 解释: 从根到叶子节点路径4->9->5
代表数字 495 从根到叶子节点路径4->9->1
代表数字 491 从根到叶子节点路径4->0
代表数字 40 因此,数字总和 = 495 + 491 + 40 =1026
提示:
- 树中节点的数目在范围
[1, 1000]
内 0 <= Node.val <= 9
- 树的深度不超过
10
/**
* 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 sumNumbers(TreeNode* root) {
}
};
解析代码
也是dfs的代码,要把当前值传下去,递归下面的①②③④步:
/**
* 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 sumNumbers(TreeNode* root) {
return dfs(root, 0);
}
int dfs(TreeNode* root, int sum)
{
sum = sum*10 + root->val;
if(root->left == nullptr && root->right == nullptr)
return sum;
int ret = 0;
if(root->left) // 如果左子树不为空
ret += dfs(root->left, sum);
if(root->right)
ret += dfs(root->right, sum);
return ret;
}
};
③力扣814. 二叉树剪枝
814. 二叉树剪枝
难度 中等
给你二叉树的根结点 root
,此外树的每个结点的值要么是 0
,要么是 1
。
返回移除了所有不包含 1
的子树的原二叉树。
节点 node
的子树为 node
本身加上所有 node
的后代。
示例 1:
输入:root = [1,null,0,0,1] 输出:[1,null,0,null,1] 解释: 只有红色节点满足条件“所有不包含 1 的子树”。 右图为返回的答案。
示例 2:
输入:root = [1,0,1,0,0,0,1] 输出:[1,null,1,null,1]
示例 3:
输入:root = [1,1,0,1,1,0,1,0] 输出:[1,1,0,1,1,null,1]
提示:
- 树中节点的数目在范围
[1, 200]
内 -
Node.val
为0
或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:
TreeNode* pruneTree(TreeNode* root) {
}
};
解析代码
题意就是删除所有元素只有0的子树,解题思路就是递归+后序遍历:
相信递归一定能把左右子树都剪枝了,出口是碰到叶子结点,函数体是如果这个结点的左结点和右结点都为空,并且值为0,就剪掉。
/**
* 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:
TreeNode* pruneTree(TreeNode* root) {
/*
题意就是删除所有元素只有0的子树,解题思路就是递归+后序遍历:
相信递归一定能把左右子树都剪枝了,出口是碰到叶子结点,
函数体是如果这个结点的左结点和右结点都为空,并且值为0,就剪掉。
*/
if(root == nullptr)
return nullptr;
root->left = pruneTree(root->left);
root->right = pruneTree(root->right);
if(root->left == nullptr && root->right == nullptr && root->val == 0)
{
delete root; // 可加可不加,面试时可以问结点是不是new出来的,不然会报错
root = nullptr;
}
return root;
}
};
④力扣98. 验证二叉搜索树
98. 验证二叉搜索树
难度 中等
给你一个二叉树的根节点 root
,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
- 节点的左子树只包含 小于 当前节点的数。
- 节点的右子树只包含 大于 当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
示例 1:
输入:root = [2,1,3] 输出:true
示例 2:
输入:root = [5,1,4,null,null,3,6] 输出:false 解释:根节点的值是 5 ,但是右子节点的值是 4 。
提示:
- 树中节点数目范围在
[1, 10^4]
内 -2^31 <= Node.val <= 2^31 - 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:
}
};
解析代码
一颗二叉搜索树中序遍历一定是有序的:
/**
* 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 {
long prev = LONG_MIN; // 存储中序遍历前驱的值
public:
bool isValidBST(TreeNode* root) {
if(root == nullptr)
return true;
bool left = isValidBST(root->left); // 判断左子树
if(left == false) // 剪枝
return false;
bool flag = false;
if(root->val > prev) // 判断自己
{
flag = true;
}
if(flag == false) // 剪枝
return false;
prev = root->val;
bool right = isValidBST(root->right); // 判断右子树
return left && right && flag;
}
};
⑤力扣230. 二叉搜索树中第K小的元素
230. 二叉搜索树中第K小的元素
难度 中等
给定一个二叉搜索树的根节点 root
,和一个整数 k
,请你设计一个算法查找其中第 k
个最小元素(从 1 开始计数)。
示例 1:
输入:root = [3,1,4,null,2], k = 1 输出:1
示例 2:
输入:root = [5,3,6,2,4,null,null,1], k = 3 输出:3
提示:
- 树中的节点数为
n
。 1 <= k <= n <= 10^4
0 <= Node.val <= 10^4
进阶:如果二叉搜索树经常被修改(插入/删除操作)并且你需要频繁地查找第 k
小的值,你将如何优化算法?
/**
* 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 kthSmallest(TreeNode* root, int k) {
};
解析代码
思路就是中序遍历到第K个结点,然后返回这个结点的值,可以弄两个全局变量来简化代码。
/**
* 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 {
int cnt = 0, ret = 0;
public:
int kthSmallest(TreeNode* root, int k) {
cnt = k;
dfs(root);
return ret;
}
void dfs(TreeNode* root)
{
if(root == nullptr || cnt == 0)
return;
dfs(root->left); // 遍历左子树
if(--cnt == 0) // 判断
ret = root->val;
dfs(root->right); // 遍历右子树
}
};
⑥力扣257. 二叉树的所有路径
257. 二叉树的所有路径
难度 简单
给你一个二叉树的根节点 root
,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [1,2,3,null,5] 输出:["1->2->5","1->3"]
示例 2:
输入:root = [1] 输出:["1"]
提示:文章来源:https://www.toymoban.com/news/detail-841107.html
- 树中节点的数目在范围
[1, 100]
内 -100 <= Node.val <= 100
/**
* 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:
vector<string> binaryTreePaths(TreeNode* root) {
}
};
解析代码
思路就是遍历到叶子结点就push当前路径, 到最后剪枝,不用写函数出口。文章来源地址https://www.toymoban.com/news/detail-841107.html
/**
* 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 {
vector<string> ret;
public:
vector<string> binaryTreePaths(TreeNode* root) {
dfs(root, "");
return ret;
}
void dfs(TreeNode* root, string path)
{
path += to_string(root->val); // 不可能传空root进来
if(root->left == nullptr && root->right == nullptr)
{
ret.push_back(path); // 是叶子结点就push当前路径
}
else // 不是叶子结点就先加上箭头
{
path += "->";
}
if(root->left != nullptr) // 剪枝,此时不用写函数出口
dfs(root->left, path);
if(root->right != nullptr)
dfs(root->right, path);
}
};
到了这里,关于Offer必备算法08_二叉树dfs_六道力扣题详解(由易到难)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!