持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情
101. 对称二叉树
思路
(递归) O(n)
给定我们一个二叉树的根节点root
,检查这颗二叉树是否轴对称。
样例:
如样例所示,root = [1,2,2,3,4,4,3]
,是一颗轴对称二叉树,因此我们返回true
。判断一棵二叉树是否轴对称,其实就是判断这颗二叉树的左右两个子树是否互为镜像。
两个子树互为镜像当且仅当:
- 两个子树的根节点值相等;
- 第一棵子树的左子树和第二棵子树的右子树对称,且第一棵子树的右子树和第二棵子树的左子树对称;
具体实现过程如下:
- 1、我们定义两个指针
p
和q
,让p
和q
指针一开始分别指向左子树和右子树。 - 2、同步移动这两个指针来遍历这棵树,每次检查当前
p
和q
节点的值是否相等,如果相等再判断左右子树是否对称。
判断两颗树对称的递归边界:
p
和q
节点都为空时,左右子树都为空,返回true
p
和q
节点只有一个为空时,左右子树不对称,返回false
p
和q
节点值不相等,左右子树不对称,返回false
时间复杂度分析: 从上到下每个节点仅被遍历一遍,所以时间复杂度是 O(n)。
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) return true;
return dfs(root->left, root->right);
}
bool dfs(TreeNode* p, TreeNode* q){
if(!p && !q) return true;
if(!p || !q) return false;
if(p->val != q->val) return false;
return dfs(p->left, q->right) && dfs(p->right, q->left);
}
};
102. 二叉树的层序遍历
思路
(BFS) O(n) 我们从根节点开始按宽度优先的顺序遍历整棵树,每次先扩展左儿子,再扩展右儿子。
这样我们会:
- 先扩展根节点;
- 再依次扩展根节点的左右儿子,也就是从左到右扩展第二层节点;
- 再依次从左到右扩展第三层节点;
- 依次类推
然后在遍历过程中我们给每一层加一个结尾标记NULL
,当我们访问到一层的结尾时,由于BFS
的特点,我们刚好把下一层都加到了队列中。这个时候就可以给这层加上结尾标记NULL
了,每次遍历到一层的结尾NULL
时,就将这一层添加到结果中。
时间复杂度分析: 每个节点仅会被遍历一次,因此时间复杂度为O(n)。
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:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
vector<int> path;
queue<TreeNode*> q;
q.push(root);
q.push(nullptr);
while(q.size()){
TreeNode* t = q.front();
q.pop();
if(!t){
if(path.empty()) break; //如果当前层没有元素,直接结束(防止进入死循环)
res.push_back(path);
path.clear();
q.push(nullptr); //每一层的结尾加一个null标记结束
}else{
path.push_back(t->val);
if(t->left) q.push(t->left);
if(t->right) q.push(t->right);
}
}
return res;
}
};
104. 二叉树的最大深度
思路
(递归) O(n) 当前树的最大深度等于左右子树的最大深度加1
,也就是说如果我们知道了左子树和右子树的最大深度 lh
和 rh
,那么该二叉树的最大深度即为 max(lh,rh) + 1
图示:
递归设计:
- 1、递归边界:当前节点为空时,树的深度为
0
- 2、递归返回值:返回当前子树的深度,即
max(lh,rh) + 1
时间复杂度分析: 树中每个节点只被遍历一次,所以时间复杂度是 O(n)。
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:
int maxDepth(TreeNode* root) {
if(!root) return 0;
int lh = maxDepth(root->left), rh = maxDepth(root->right);
return max(lh, rh) + 1;
}
};