心得:使用递归法大多用后序不会出错。递归可以精简,但精简完逻辑就不明显了。
求数量,深度这种东西,如果root是空,就返回0。
原则上来说,求二叉树的高度是从下往上遍历,应该使用后序遍历;而深度则相反,从上往下应该使用前序遍历。但二叉树的最大深度正好是其根节点的高度,所以用后序也可以。
第一题、二叉树的最大深度 LeetCode104 https://leetcode.cn/problems/maximum-depth-of-binary-tree/
二叉树的高度和深度:
首先当然可以使用迭代法层序遍历,记录一些while循环的次数即可:
class Solution {
public:
int maxDepth(TreeNode* root) {
queue que;
if(root != NULL) que.push(root);
int maxDepth = 0;
while(!que.empty()){
int size = que.size();
vector vec;
for(int i = 0; i < size; i++){
TreeNode* node = que.front();
que.pop();
vec.push_back(node->val);
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
//size++;
}
maxDepth++;
}
return maxDepth;
}
};
也可以用递归法:
class Solution {
public:
int getDepth(TreeNode* node){
//后序
if(node == NULL) return 0;
int leftDepth = getDepth(node->left);//左
int rightDepth = getDepth(node->right);//右
int depth = 1 + max(leftDepth, rightDepth);//中
return depth;
}
int maxDepth(TreeNode* root) {
return getDepth(root);
}
};
N叉数的最大深度 LeetCode 559 https://leetcode.cn/problems/maximum-depth-of-n-ary-tree/
递归:可以直接在一个函数里面递归。
class Solution {
public:
int maxDepth(Node* root) {
if(root == NULL) return 0;
int depth = 0;
for(int i = 0; i < root->children.size(); i++){
depth = max(depth, maxDepth(root->children[i]));
}
return 1 + depth;
}
};
也可使用层序遍历:记住depth自加的位置,不是在同一层内的遍历里。
class Solution {
public:
int maxDepth(Node* root) {
queue que;
int depth = 0;
if(root != NULL) que.push(root);
while(!que.empty()){
int size = que.size();
depth++;
for(int i = 0; i < size; i ++){
//depth++;不在这里加,这里是遍历同一层之内的节点
Node* node = que.front();
que.pop();
for(int i = 0; i < node->children.size(); i++){
if(node->children[i]) que.push(node->children[i]);
}
}
}
return depth;
}
};
第二题 二叉树的最小深度 LeetCode 111 https://leetcode.cn/problems/minimum-depth-of-binary-tree/
可以用迭代法:
class Solution {
public:
int minDepth(TreeNode* root) {
//迭代
queue que;
if(root != NULL) que.push(root);
int depth = 0;
while(!que.empty()){
int size = que.size();
depth++;
for(int i = 0; i < size; i++){
TreeNode* node = que.front();
que.pop();
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
if(node->left == NULL && node->right == NULL) return depth;
}
}
return depth;
}
};
用递归:
class Solution {
public:
int getDepth(TreeNode* node){
if(node == NULL) return 0;
int leftDepth = getDepth(node->left);
int rightDepth = getDepth(node->right);
// 当一个左子树为空,右不为空,这时并不是最低点
if(node->left != NULL && node->right == NULL){
return 1 + leftDepth;
}
// 当一个右子树为空,左不为空,这时并不是最低点
if(node->left == NULL && node->right != NULL){
return 1 + rightDepth;
}
int res = 1 + min(leftDepth, rightDepth);
return res;
}
int minDepth(TreeNode* root) {
//迭代
return getDepth(root);
}
};
第三题:完全二叉树的节点数 LeetCode222 https://leetcode.cn/problems/count-complete-tree-nodes/
当然可以当作普通二叉树,层序遍历所有节点:
class Solution {
public:
int countNodes(TreeNode* root) {
queue que;
if(root != NULL) que.push(root);
int count = 0;
while(!que.empty()){
int size = que.size();
vector vec;
for(int i = 0; i < size; i++){
TreeNode* node = que.front();
que.pop();
vec.push_back(node->val);
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
count++;
}
}
return count;
}
};
也可以利用完全二叉树的特性,遍历左子树的完全二叉树,不需要遍历所有的节点。
class Solution {
public:
int countNodes(TreeNode* root) {
if(root == NULL) return 0;
TreeNode* left = root->left;
TreeNode* right = root->right;
int leftDepth = 0, rightDepth = 0;
while(left){
left = left->left;
leftDepth++;
}
while(right){
right = right->right;
rightDepth++;
}
if(leftDepth == rightDepth) return (2 << leftDepth) - 1;
return countNodes(root->left) + countNodes(root->right) + 1;
}
};