代码随想录day16-二叉树(4)

代码随想录day16-二叉树(4)

1、LeetCode 222 完全二叉树的节点个数

题目分析:

本题要求统计完全二叉树的结点个数。首先我们不按照完全二叉树的思路来的话,直接就为了统计结点的个数,那么使用深度优先以及广度优先都是可以办到的,但是我们没有充分利用完全二叉树的特点。
完全二叉树可以分为满二叉树普通的完全二叉树。对于满二叉树而言,每一层的是满的,我们只要得到了层数i,那么节点的个数即使 2 i − 1 2^i-1 2i1个。那么如何判断二叉树是不是满二叉树呢?
我们只需要沿着根节点不断向左,以及不断向右,记录到叶子结点的层数,如果左右层数相等,就说明这个二叉树是满二叉树。
然后对于一些普通话的完全二叉树的,我们就可以使用后序遍历来做。

题目解答:

递归法:(使用后序遍历)

class Solution {
public:
    int countNodes(TreeNode* root) {
        if (root == nullptr) return 0;
        
        int leftCountNode = countNodes(root->left);  // 左
        int rightCountNode = countNodes(root->right);  // 右
        return 1 + leftCountNode + rightCountNode;
    }
};

层序遍历法:

class Solution {
public:
    int countNodes(TreeNode* root) {
        if (root == nullptr) return 0;
        // 使用层序遍历法也是可以做的
        queue<TreeNode*> que;
        que.push(root);
        int ans = 0;
        while (!que.empty()) {
            int size = que.size();
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                ans++;
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }    
        }
        return ans;
    }
};

上述的两种方法都没有很好的利用完全二叉树的特性,以下是更好的解法:

/**
 * 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) {}
 * };
 */
class Solution {
public:
    int countNodes(TreeNode* root) {
        // 注意这个题目给定的就完全二叉树,可以充分利用完全二叉树的性质
        if (root == nullptr) return 0;  //  遇到空结点就返回
        TreeNode* left = root->left;
        TreeNode* right = root->right;
        int leftDepth = 0, rightDepth = 0; // 这里初始为0是有目的的,为了下面求指数方便

        // 判断子树是不是满二叉树,如果左结点一直向左的深度等于右结点一直向右的深度,就代表是满二叉树
        while (left) {
            left = left->left;
            leftDepth++;
        }
        while (right) {
            right = right->right;
            rightDepth++;
        }
        if (leftDepth == rightDepth) return (2 << leftDepth) - 1;  // 满二叉树的结点个数是2^i - 1

        // 下面就是非满二叉树的情况
        int leftTreeNum = countNodes(root->left);       // 左
        int rightTreeNum = countNodes(root->right);     // 右
        int result = leftTreeNum + rightTreeNum + 1;    // 中
        return result;
    }
};

上述的方法单独判断了是不是满二叉树的情况

2、LeetCode 110 平衡二叉树

题目分析:

本题也可以使用后序遍历的方法求左右子树的高度,然后比较其高度差是不超过1即可。

题目解答:
class Solution {
public:
    // 肯定是需要计算得到树的高度的
    int getHeight( TreeNode* node) {
        if (node == nullptr) return 0;

        int leftHeight = getHeight(node->left);
        if (leftHeight == -1) return -1;  // 注意这里为什么需要加这两个条件
        int rightHeight = getHeight(node->right);
        if (rightHeight == -1) return -1;

        // 如果高度差超过1,说明肯定不是平衡二叉树,直接返回-1
        if (abs(leftHeight - rightHeight) > 1) {
            return -1;
        }
        return 1 + max(leftHeight, rightHeight);
    }

    bool isBalanced(TreeNode* root) {
        return getHeight(root) == -1 ? false : true;
    }
};

注意: 上述代码里面的if (leftHeight == -1) return -1;以及if (rightHeight == -1) return -1;不能缺少,因为以根节点的左右结点为根节点的左右子树都不是平衡树的话,那肯定就是不符合答案的。
如果没有这两句话,那么假设**leftHeight = -1, rightHeight = -1**的话,这个时候是不满足题意的,但是返回的却是1,即判定为平衡树。所以这里需要注意。

通过本题可以了解求二叉树深度 和 二叉树高度的差异,求深度适合用前序遍历,而求高度适合用后序遍历

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值