前序:
二叉树的遍历:前序遍历,中序遍历,后序遍历,主要解决问题是利用这三种方法对其进行计算
一:计算布尔二叉树的值
题目:
有一个完整二叉树,有以下特征:
叶子结点要么为0,要么为1,分别表示false, true
非叶子节点要么为2,要么为3,分别表示逻辑或,与逻辑与
计算一个叶子结点的值为:
如果节点为叶子结点,节点的值为它本身,即为false, true
如果为非叶子节点,要计算两个孩子的节点值,然后将该节点的运算符对两个孩子进行运算
返回根节点root的布尔值
示例:
分析:
非叶子节点表示逻辑词,叶子节点表示对错, 二叉树又为完整二叉树,要得到整个二叉树的布尔值,要先从最下面开始,得到每个非叶子节点左右子树的布尔值,适用于后序遍历
函数头:将节点的位置传过去,并返回布尔值即可
bool evaluateTree(TreeNode* root);
函数体:得到左右子树的值,然后根据根节点的值返回它的布尔值
递归出口:左右节点均为空,直接返回该节点的值
class Solution {
public:
bool evaluateTree(TreeNode* root) {
if(root->left==nullptr&&root->right==nullptr)
return root->val==0?false:true;
bool left = evaluateTree(root->left);
bool right = evaluateTree(root->right);
return root->val==2?left|right:left&right;
}
};
二:求根节点到叶节点所有数字的和
题目:
给一个二叉树的根节点root,树中每个节点分别存有0~9的值,每条从根节点到叶节点的路径分别表示一个数字。
如:从根节点到叶节点的路径为1->2->3,则表示数字123
要计算所有根节点到叶节点所有路径的数字之和!
示例:
分析:
从根节点开始,一直传着节点的值,若遇到叶子节点节点,则这条路径借宿
函数头:递归函数,需要返回一个整数值,传参要传根节点和一个原先节点的值
int dfs(TreeNode* root, int persume)
函数体:先将原先得到的值乘10再加上当前节点的值,再对是否为叶子节点进行判断
递归出口:遇到左右节点均为空,直接返回原先算出来的值
int dfs(TreeNode*root,int persume)
{
persume = persume*10+root->val;
if(root->left==nullptr&&root->right==nullptr)
return persume;
int ret = 0;
if(root->left) ret+= dfs(root->left,persume);
if(root->right) ret+= dfs(root->right,persume);
return ret;
}
三:二叉树的剪枝
题目:
给一个二叉树的根节点,此外每个节点的值为要么为1,要么为0,返回移除了所有不包含1的子树的原子数。
示例:
分析:
要先判断左右子树是否为空,然后根据本身节点的值是否为0进行判断是否要对齐进行删除,要利用的为后序遍历
函数头:返回节点地址,传参节点的地址
TreeNode* pruneTree(TreeNode* root)
函数体:先判断本身节点是否为空,然后对左右子树进行处理,之后再根据本身节点的值进行判断要不要进行剪枝
递归出口:节点为空,直接返回空,之后直接返回root
TreeNode* pruneTree(TreeNode* root) {
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)
{
root = nullptr;
}
return root;
}
四:验证二叉搜索树
题目:
给一个二叉树,判断是否为有效的搜索二叉树
有效搜索树:
节点左子树只包含小于当前节点的数
节点右子树只包含大于当前节点的数
所有·左子树和右子树都要为有效的搜索二叉树
PS:二叉搜索树的中序遍历的结果为一个有序的序列
示例:
分析以及一些重要的算法方法:
1:全局变量的优势:减少传参的个数,可以对其直接进行改变
2:回溯:在深入遍历时,一般都存在着回溯
3:剪枝:加速搜索过程
思路:使用中序遍历,用一个值存放前一个节点的值,分别得到左右子树的值,再将根节点与之进行比较,如果大小关系符合就返回true,不符合返回false
分析:先判断左右子树是否为搜索二叉树,再加上本身进行判断
class Solution {
public:
long prev = LONG_MIN;
bool isValidBST(TreeNode* root) {
if(root==nullptr)return true;
bool left = isValidBST(root->left);
//剪枝
if(left==false) return false;
bool cur = false;
if(root->val>prev)
cur = true;
prev = root->val;
bool right = isValidBST(root->right);
return left&&right&&cur;
}
};
五:查找二叉搜索树中第k小的元素
题目:
给定一个二叉搜索树的根节点 root,和一个整数 k
,请你设计一个算法查找其中第 k
小的元素(从 1 开始计数)
PS:搜索二叉树的中序遍历为一个有序的序列
分析:
总体思路:全局变量加中序遍历
先设立两个全局变量,一个存放最后要用的值,一个用来计数遍历的次数
class Solution {
int cout;
int ret;
public:
int kthSmallest(TreeNode* root, int k) {
cout = k;
dfs(root);
return ret;
}
void dfs(TreeNode* root)
{
if(root==nullptr||cout==0) return;
dfs(root->left);
cout--;
if(cout==0) ret = root->val;
dfs(root->right);
}
};
六:二叉树的所有路径
题目:
给一个根节点,按任何顺序返回,从根节点到叶节点的所有路径
分析:
使用前序遍历对二叉树进行遍历,使用传参的方法实现回溯更加方便
创立一个全局变量string,用来存放各个路径的字符串
class Solution {
public:
vector<string> ret;
vector<string> binaryTreePaths(TreeNode* root) {
string path;
if(root==nullptr) return ret;
dfs(root,path);
return ret;
}
void dfs(TreeNode* root,string path)
{
path += to_string(root->val);
if(root->left==nullptr&&root->right==nullptr)
{
ret.push_back(path);
return;
}
path+="->";
if(root->left) dfs(root->left,path);
if(root->right) dfs(root->right,path);
}
};