0 初始思路(DFS)
0.1 90%DFS— O ( n ) O(n) O(n)
初看题目,直接思路就是按完全二叉树的性质分两种情况讨论
- 二叉树是满二叉树(最后一层叶节点没有缺失)
- 二叉树是非满二叉树(最后一层右侧集中缺失若干叶节点)
但当初没有往深想,只是简单判断整个树若是满二叉树,则用公式
2
h
−
1
2^h - 1
2h−1来求,其余情况又是时间复杂度为
O
(
n
)
O(n)
O(n)的dfs
了,此外也没有用到位运算,所以效率大打折扣。
class Solution {
public:
int dfs(TreeNode* root, int left_high, int cur_high) {
if (!root && (cur_high == left_high)) return 1;
if (!root && (cur_high != left_high)) return 0;
return dfs(root->right, left_high, cur_high + 1) + dfs(root->left, left_high, cur_high + 1);
}
int countNodes(TreeNode* root) {
if (!root) return 0;
int left_high = 1;
int right_high = 1;
auto node_left = root;
auto node_right = root;
while (node_right->right) {
node_right = node_right->right;
right_high++;
node_left = node_left->left;
left_high++;
}
if (!node_left->left) return pow(2, left_high) - 1;
left_high++;
return pow(2, left_high) - 1 - dfs(root, left_high, 1);
}
};
0.2 100%DFS— O ( n ) O(n) O(n)
此处就当成普通二叉树的问题去变量了,因此时间复杂度也是 O ( n ) O(n) O(n)
class Solution {
public:
int countNodes(TreeNode* root) {
if (!root) return 0;
int left = countNodes(root->left);
int right = countNodes(root->right);
return left + right + 1;
}
};
1 位运算 + 运用满二叉树性质快速遍历
class Solution {
public:
int countNodes(TreeNode* root) {
if (!root) return 0;
int left_high = 0; // 取0方便求指数
auto left_node = root;
auto right_node = root;
while (right_node->right) {
right_node = right_node->right;
left_node = left_node->left;
left_high++;
}
if (!left_node->left) return (2 << left_high) - 1; // 注意(2<<1) 相当于2^2,所以left_high初始为0
return countNodes(root->left) + countNodes(root->right) + 1; // +1是要加上当前root节点
}
};
致谢
感谢「代码随想录」公众号梳理的思路,欢迎大家关注这位大佬的公号