【leetcode】【完全二叉樹】222. Count Complete Tree Nodes
阿新 • • 發佈:2021-11-19
Given therootof acompletebinary tree, return the number of the nodes in the tree. According toWikipedia, every level, except possibly the last, is completely filled in a complete binary tree, and all nodes in the last level are as far left as possible. It can have between1and2hnodes inclusive at the last levelh. Design an algorithm that runs in less thanO(n)time complexity.
完全二叉樹:設二叉樹的深度為h,除第 h 層外,其它各層 (1~h-1) 的結點數都達到最大個數,第 h 層所有的結點都連續集中在最左邊
題目要求時間複雜度小於O(n) 該如何處理呢?
/** * 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) {} * };對於完全二叉樹,去掉最後一層,就是一棵滿二叉樹,我們知道高度為 h 的滿二叉樹結點的個數為 2^h - 1 個,所以要知道一棵完全二叉樹的結點個數,只需知道最後一層有多少個結點。而完全二叉樹最後一層結點是從左至右連續的,所以我們可以依次給它們編一個號,然後二分搜尋最後一個葉子結點。我是這樣編號的,假設最後一層在 h 層,那麼一共有 2^(h-1) 個結點,一共需要 h - 1 位來編號,從根結點出發,向左子樹走編號為 0, 向右子樹走編號為 1,那麼最後一層的編號正好從0 ~ 2^(h-1) - 1。複雜度為 O(h*log(2^(h-1))) = O(h^2)。*/ class Solution { public: int countNodes(TreeNode* root) { //為啥要設計一個時間複雜度小於n的演算法 //完全二叉樹的特性 o(n)的比較好寫 // 先寫o(n)複雜的的 int res=0; if(root==nullptr) return res; stack<TreeNode* > dp; dp.push(root); while(!dp.empty()){ TreeNode* node=dp.top(); res++; dp.pop(); if(node->left!=nullptr){ dp.push(node->left); } if(node->right!=nullptr){ dp.push(node->right); } } return res; } };
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: bool isOK(TreeNode *root, int h, int v) { TreeNode *p = root; for (int i = h - 2; i >= 0; --i) { if (v & (1 << i)) p = p->right; else p = p->left; } return p != NULL; } int countNodes(TreeNode* root) { if (root == NULL) return 0; TreeNode *p = root; int h = 0; while (p != NULL) { p = p->left; ++h; } int l = 0, r = (1 << (h - 1)) - 1, m; while (l <= r) { m = l + ((r - l) >> 1); if (isOK(root, h, m)) l = m + 1; else r = m - 1; } return (1 << (h - 1)) + r; } };