完全二叉树的节点个数
原题在这里:
概述题意,要求比O(n)复杂度更好的求出完全二叉树的节点数量的算法。
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) {} };
analyse:
1.利用完全二叉树的性质,分类讨论:
class Solution { int dfs(TreeNode *n) { int ans = 0; while (n != nullptr) { n = n->left; ++ans; } return ans; } public: int countNodes(TreeNode *root) { /* analyse: 利用完全二叉树的性质,分类为4中情况 令左右子树高度分别为lr,那么有: 当l==r时候,左子树一定是满的,那么使用2^l-1求答案 当l!=r时候,右子树一定不满,那么使用2^r-1求答案 */ if (!root) return 0; int l = dfs(root->left); //左子树深度 int r = dfs(root->right); //右子树深度 if (l == r) return (1 << l) + countNodes(root->right); //如果相同,则往右取 return (1 << r) + countNodes(root->left); //否则往左取 } };
2.如上的另一种写法:
class Solution { int leftDepth(TreeNode *root) { return root ? 1 + leftDepth(root->left) : -1; } public: int countNodes(TreeNode *root) { /* analyse: 利用完全二叉树的性质,分类为4中情况 令左右子树高度分别为lr,那么有: 当l==r时候,左子树一定是满的,那么使用2^l-1求答案 当l!=r时候,右子树一定不满,那么使用2^r-1求答案 另一种写法。 */ if (!root) return 0; int d = leftDepth(root), res = 0; while (root) { // cout << "访问节点:" << root->val << endl; int rd = leftDepth(root->right); //右子树深度r与当前深度n的关系只有 n=r+1 or n = r if (d == rd + 1) { //右子树深度小,右走 // cout << " +=" << (1 << d) << endl; res += 1 << d; root = root->right; } else { //两子树深度相同,左走 // cout << " +=" << (1 << (d - 1)) << endl; res += 1 << (d - 1); root = root->left; } --d; // crutial, reduce total depth for subtree } return res; } };
3.另外一种思路是用二分搜索节点,因为二分搜索的细节原因(懂的都懂,不懂的也不多说),就不写了。
【Over】

浙公网安备 33010602011771号