代码随想录算法训练营第16天 | 104.二叉树的最大深度, 111.二叉树的最小深度, 222.完全二叉树的节点个数

104.二叉树的最大深度

代码随想录链接

题目

返回给定二叉树的最大深度.

自己的想法

层序遍历一下, 返回最后一层深度.

题解

层序遍历:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 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 depth = 0;
queue<TreeNode *> que;
que.push(root);
while (!que.empty()) {
int qsize = que.size();
depth++; // 每遍历一层, depth就自增1
for (int i = 0; i < qsize; i++) {
TreeNode *node = que.front();
que.pop();
if (node -> left) que.push(node -> left);
if (node -> right) que.push(node -> right);
}
}
return depth;
}
};

递归法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 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;

return 1 + max(maxDepth(root -> left), maxDepth(root -> right)); // 左侧节点个数 + 右侧节点个数 + 自身
}
};

111.二叉树的最小深度

代码随想录链接

题目

返回二叉树的最小深度.

自己的想法

层序遍历, 在遇到第一个无左右孩子的节点时, 返回当前深度.

题解

层序遍历:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
* 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 minDepth(TreeNode* root) {
if (!root) return 0;
queue<TreeNode *> que;
que.push(root);
int level = 0;
while (!que.empty()) {
level++;
int qsize = que.size();
for (int i = 0; i < qsize; i++) {
TreeNode *node = que.front();
que.pop();
if (!(node -> left) && !(node -> right)) return level; // 遇到无左右孩子的节点就返回当前深度
if (node -> left) que.push(node -> left);
if (node -> right) que.push(node -> right);
}
}
return level;
}
};

递归:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 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 minDepth(TreeNode* root) {
if (root == nullptr) return 0;
if ((root -> left == nullptr) && (root -> right != nullptr)) return 1 + minDepth(root -> right); // 只有右孩子就只计算右子树的最小深度
if ((root -> left != nullptr) && (root -> right == nullptr)) return 1 + minDepth(root -> left); // 只有左孩子就只计算左子树的最小深度
return 1 + min(minDepth(root -> left), minDepth(root -> right)); // 左右孩子都有就取左右子树的最小值
}
};

222.完全二叉树的节点个数

代码随想录链接

题目

统计给定的完全二叉树有多少个节点.

自己的想法

不管什么遍历, 个数查一下. 但时间复杂度是\(O(n)\).

应该要针对于完全二叉树的特性, 使用一些方法来降低时间复杂度.

题解

当做普通二叉树来层序遍历:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 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 countNodes(TreeNode* root) {
if (!root) return 0;
int count = 0;
queue<TreeNode *> que;
que.push(root);
while (!que.empty()) {
int qsize = que.size();
for (int i = 0; i < qsize; i++) {
TreeNode *node = que.front();
que.pop();
count++; // 查个数
if (node -> left) que.push(node -> left);
if (node -> right) que.push(node -> right);
}
}
return count;
}
};

当做普通二叉树来递归:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 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 countNodes(TreeNode* root) {
if (!root) return 0;
return 1 + countNodes(root -> left) + countNodes(root -> right);
}
};

针对完全二叉树的特性, 来优化时间复杂度. 完全二叉树的叶子结点一定是积累在最后一层的靠左部分. 其中部分子树是满二叉树, 满足从任意节点出发, 最左下的节点和最后下的节点与出发节点的高度差一致的特性. 可以在计算时, 判断当前节点出发的树是否是满二叉树, 如果是, 用公式计算即可, 如果不是, 再使用类似于上面的递归方法来统计节点个数.

针对完全二叉树的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
* 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 countNodes(TreeNode* root) {
if (!root) 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; // 若子树不是完全二叉树, 就递归计算这个子树的个数
}
};

代码随想录算法训练营第16天 | 104.二叉树的最大深度, 111.二叉树的最小深度, 222.完全二叉树的节点个数

http://wwg.xyz/algorithm-train-day16/

作者

Giles

发布于

2023-03-02

更新于

2023-03-13

许可协议

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×