對於讓你求二叉樹節點個數的題目,無非就是普通二叉樹、完全二叉樹、滿二叉樹三種。這三者的關系是,二叉樹>完全二叉樹>滿二叉樹。
如果是題目沒有給限定條件,只讓你求二叉樹的節點個數,則按照普通二叉樹來求;如果給了限定條件,完全二叉樹或者滿二叉樹,則根據他們的特性有更優化的算法。
一、求普通二叉樹的節點個數
遞歸算法和迭代算法:
/** * 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: int countNodes(TreeNode* root) { //用遞歸的方式,用遞歸真的太簡單了 //if(root == NULL) // return 0; //return 1+countNodes(root->left)+countNodes(root->right);//屬於后序遍歷,先求了子樹的,然后加上了中間的根節點 //還可以采用層序遍歷的方式,稍微改動模板,其實前序后序中序遍歷感覺都行 if(root == NULL) return 0; queue<TreeNode*> que; que.push(root); int result = 0; while(!que.empty()) { int size = que.size(); 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); result++; } } return result; } };
着重說一下這種遞歸算法的時間復雜度是O(n)
二、求滿二叉樹的節點個數
滿二叉樹也是普通二叉樹,用求普通二叉樹節點個數的方法完全能夠得到正確答案,但是我們一開始說了,既然給定了這個條件,我們就能根據它的特性得到簡單的解法。
滿二叉樹的節點個數是跟二叉樹的深度有關系的,節點個數n=2^(深度)-1,根據這個特性,我們只需要知道二叉樹的深度,就能得到節點個數。
/** * 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: int countNodes(TreeNode* root) { int h = 0; //計算樹的高度 while(root!=nullptr) { root = root->left; h++; } return (int)math.pow(2,h)-1; } };
while循環只需要logN的時間,所以時間復雜度為O(logN)。
三、求完全二叉樹的節點個數
完全二叉樹也是普通二叉樹,用求普通二叉樹節點個數的方法完全能夠得到正確答案,但是我們一開始說了,既然給定了這個條件,我們就能根據它的特性得到簡單的解法。
完全二叉樹的的兩棵子樹,至少有一顆是滿二叉樹。既然有這個特點,那這棵滿二叉樹就可以節省時間,另一棵當做普通二叉樹計算。
/** * 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: int countNodes(TreeNode* root) { TreeNode* leftNode = root; TreeNode* rightNode = root; //得到左右子樹的高度 int lh=0, rh=0; while(leftNode != nullptr) { leftNode = leftNode->left; lh++; } while(rightNode != nullptr) { rightNode = rightNode->right; rh++; } //如果左右子樹的高度相同,說明是一棵滿二叉樹 if(lh == rh) return pow(2,lh)-1; //如果高度不相等,按照普通二叉樹的計算邏輯 return 1+countNodes(root->left)+countNodes(root->right); } };
這個算法的時間復雜度為O(logNlogN)。因為while循環的時間是O(logN),遞歸的時候因為上面提到的特性,只會遞歸一支子樹,遞歸深度就是樹的高度O(logN),所以總體的時間復雜度是O(logNlogN)。