求二叉樹的節點個數總結


對於讓你求二叉樹節點個數的題目,無非就是普通二叉樹、完全二叉樹、滿二叉樹三種。這三者的關系是,二叉樹>完全二叉樹>滿二叉樹。

如果是題目沒有給限定條件,只讓你求二叉樹的節點個數,則按照普通二叉樹來求;如果給了限定條件,完全二叉樹或者滿二叉樹,則根據他們的特性有更優化的算法。

一、求普通二叉樹的節點個數

遞歸算法和迭代算法:

/**
 * 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)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM