二叉树
1.二叉树的概念
二叉树:n(n≥0)个结点的有限集,或者为空(n=0),或者由一个根结点及两棵互不相交的、分别称作该根的左子树和右子树的二叉树组成。
即使只有一个孩子,也要严格区分左右 。且二叉树和树是两种树结构。
2.二叉树的基本形态
空树、仅有根、左子树为空、右子树为空、左子树与右子树均不为空。
3.二叉树的遍历
遍历:沿某条搜索路径周游二叉树,对每个结点访问一次且仅访问一次。
对非线性结构遍历,得到结点按某种次序排列的一个线性序列,所以遍历可看成非线性结构到线性结构的一种映射方法。
二叉树的遍历有两个:层次遍历和递归遍历。
递归遍历:
如果限定先左后右,则二叉树遍历方式有三种:
前序:DLR、中序:LDR、后序:LRD(此时二叉树由根结点D、左子树L、右子树R构成)。
层次遍历:按二叉树的层序编号的次序访问各结点。
94.二叉树的中序遍历
题目描述[简单]:
给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
示例1:
输入:root = [1,null,2,3]
输出:[1,3,2]
思想[递归]:
首先我们先看中序遍历的定义:
若二叉树为空,则空操作返回;
否则:
①中序遍历根结点的左子树;
②访问根结点;
③中序遍历根结点的右子树。
根据其性质,我们要用递归不断套用,很容易写出其代码。
C++代码:
/**
* 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:
void inorder(TreeNode* root, vector<int>& r) {
if(root!=NULL) {
inorder(root->left, r); //中根遍历左子树
r.push_back(root->val); //访问根,在尾部加入一个数据。
inorder(root->right, r); //中根遍历右子树
}
}
vector<int> inorderTraversal(TreeNode* root) { //vector容器是一个模板类,可以存放任何类型的对象
vector<int> r;
inorder(root, r);
return r;
}
};
时间复杂度:O(n),其中 n 为二叉树节点的个数。二叉树的遍历中每个节点会被访问一次且只会被访问一次。
100.相同的树
题目描述[简单]:
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
示例1:
输入:p = [1,3], q = [1,null,3]
输出:false
思路[递归]:
判断两个树是否相同,实质上是通过遍历两棵树,判断每个子树上的值是否相同。
这里我们最容易想到的是递归法。
本题判断结构相同:
先判断两树的根节点是否相同
两树根节点的左子树和右子树是否相同
判断左子树和右子树相同条件:
左子树的左子树是否相同,右子树的右子树是否相同,一直不同往下走,直到返回结果。
本题的递归条件及其结果为:
当两棵树的遍历到的节点同时为空时,返回 true。
当其中一个为空,另一个非空时,返回 false。
当两个都非空但是值不相等时,返回 false。
如果都相等,就开始就往后遍历,直接有结果或全部遍历完。
C++代码:
/**
* 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 isSameTree(TreeNode* p, TreeNode* q) {
if(p == NULL && q == NULL)
return true;
if(p == NULL || q == NULL)
return false;
if(p->val != q->val)
return false;
return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}
};
时间复杂度:O(n) n为遍历结点数。
101.对称二叉树
题目描述[简单]:
给你一个二叉树的根节点 root , 检查它是否轴对称。
示例1:
输入:root = [1,2,2,3,4,4,3]
输出:true
思路[递归]:
这几题的思路都是递归,循序渐进理解递归思想。
本题判断是否轴对称
先判断根节点,如果根节点,为空,那么是对称。
如果不为空的话,若左子树与右子树对称,则说明是对称的。
那么判断左子树和右子树对称
就是判断如果左子树的左孩子与右子树的右孩子是否对称,左子树的右孩子与右子树的左孩子是否对称,如果都i对称就说明左子树和右子树是对称的。
这就存在着递归的思想。
本题的递归条件及其结果为:
当根节点为空时,返回 true。
当往下遍历的两个节点都为空时,返回 true。
当往下遍历的两个节点中有一个为空,返回 false。
当往下遍历的两个节点的值不相等时,返回 false。
本题递归条件跟上一题差不读,但是递归对象大不相同。
本题递归对象:
左节点的左孩子 和 右节点的右孩子
左节点的右孩子 和 右节点的左孩子
C++代码:
/**
* 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 isSymmetric(TreeNode* root) {
if(root == NULL){
return true;
}
return symmetric(root->left,root->right);
}
bool symmetric(TreeNode* l,TreeNode* r){
if(l == NULL && r== NULL){
return true;
}
if(l == NULL || r == NULL || l->val != r -> val){
return false;
}
return symmetric(l->left,r->right) && symmetric(l->right,r->left);
}
};
时间复杂度:O(n)