二叉树
二叉树是也是一种经典的数据结构,在算法题目中,二叉树的题目多是基于递归的。
先给大家介绍几个关于二叉树的小结论;
- 一共有n个节点的二叉树,如果度为0的节点为x个,那么度为2的节点有x-1个
- 有一个先序遍历序列:1 2 3 4,一共有(n=4)颗二叉树满足(卡特兰数)
- 先序+中序,确定一颗二叉树
我们来看一道例题;
分析: 我们考虑一下一棵树什么时候是镜像对称的,其实就是左子树和右子树镜像对称。 那么该怎么用代码进行判断呢? 可以用两个指针p,q对称地递归遍历树,进行比较即可。
- 初始化:p=root->l,q=root->r
- 递归出口:p,q都为空,return 0
- 递归条件:p == q,p->l == q->r,p->r == q->l 特殊情况:空树也满足条件
下面是代码示例:
/**
* 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 check(TreeNode* p, TreeNode* q) {
if(p == nullptr && q == nullptr){
return 1;
}
if(!p || !q){
return 0;
}
return (p->val == q->val) && check(p->left, q->right) && check(p->right, q->left);
}
bool checkSymmetricTree(TreeNode* root) {
if(root == nullptr){
return 1;
}
else{
return check(root->left, root->right);
}
}
};
再来看一道题目:
分析: 我们找两个节点的最近公共祖先,一定和这两个节点的位置关系有关
- 如果p,q分别出现在root的左右子树中,则root是答案
- 如果p,q同时出现在root的某一个子树x中,则问题转换为在x树中找公共祖先(递归) 递归函数(root, p, q):在以root为根的树中找p,q
- root == NULL,空树,返回NULL
- root == p或者root == q,找到了一个,直接返回root。若另一个在root的子树中,root是答案。若不在,则返回找到的这个节点
- root不为空,也不是p,q,说明p,q在root的左右子树中,则递归调用,分别去左右子树中找。 l = f(root->left, p, q) r = f(root->right, p, q) (1)若l,r全为空,返回空 (2)若l,r有一个为空,返回另一个。说明在另一个子树中找到了p,q或者答案 (3)若l,r都不为空,说明p,q一边一个,则root是答案,返回root
下面是代码演示:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root == NULL){
return NULL;
}
if(root == p || root == q){
return root;
}
TreeNode* l = lowestCommonAncestor(root->left, p, q);
TreeNode* r = lowestCommonAncestor(root->right, p, q);
if(l == NULL){
return r;
}
if(r == NULL){
return l;
}
if(l && r){
return root;
}
return NULL;
}
};