Day16 二叉树 LeetCode 104 559 111 222

118 阅读3分钟

104. 二叉树的最大深度

二叉树结点高度:由下往上,该节点到根结点的最长简单路径边的条数或者结点数(取决0还是1开始计数)

二叉树结点深度:由上往下,根节点到该结点的最长简单路径边的条数或者结点数(取决0还是1开始计数)

根节点的高度即为二叉树的最大深度

心得

  • 还是没想清楚往遍历上靠,还是向一层一层往下累加,最好还行基于不同递归考虑好对应需要处理的逻辑

题解

  • 本题递归可以采用前序或者后序遍历,也可迭代法
  • 后序遍历即从地往上算高度,+1到根节点即可,前序类似逻辑往下算深度
// 递归——后序
class Solution {
public:
    int getDepth(TreeNode* root) {
        if (root == nullptr) return 0;
        int left = getDepth(root->left);
        int right = getDepth(root->right);
        return 1 + max(left, right);
    } 
    int maxDepth(TreeNode* root) {
        return getDepth(root);
    }
};
// 简化版 
class Solution {
public:
    int maxDepth(TreeNode* root) {
        return 1 + max(maxDepth(root->left),maxDepth(root->right));
    }
};

// 递归——前序

// 迭代——层序
class Solution {
public:
    int maxDepth(TreeNode* root) {
        int depth = 0;
        queue<TreeNode*> que;
        if (root == nullptr) return depth;
        que.push(root);
        while (!que.empty()) {
            depth += 1;
            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);
            }
        }
        return depth;
    }
};

559. N 叉树的最大深度

类似上题逻辑

// 递归
class Solution {
public:
    int maxDepth(Node* root) {
        int depth = 0;
        if (root == nullptr) return 0;
        for (int i = 0; i < root->children.size(); i++) {
            depth = max(depth, maxDepth(root->children[i]));
        }
        return 1 + depth;
    }
};
// 迭代
class Solution {
public:
    int maxDepth(Node* root) {
        int depth = 0;
        if (root == nullptr) return 0;
        queue<Node*> que;
        que.push(root);
        while (!que.empty()) {
            depth++;
            int size = que.size();
            while (size--) {
                Node* node = que.front();
                que.pop();
                for (int i = 0; i < node->children.size(); i++) {
                    if (node->children[i]) que.push(node->children[i]);
                }
            }
        }
        return depth;
    }
};

111. 二叉树的最小深度

心得

题解

  • 可以后序遍历,层序遍历均可,最小深度定义,左右空树情况处理,即单层处理逻辑与最大深度大不相同
// 递归——后序
class Solution {
public:
    int getDepth(TreeNode* root) {
        if (root == nullptr) return 0;
        int leftDepth = getDepth(root->left);
        int rightDepth = getDepth(root->right);
        if (root->left == nullptr && root->right != nullptr) return 1 + rightDepth;
        if (root->left != nullptr && root->right == nullptr) return 1 + leftDepth;
        return 1 + min(leftDepth, rightDepth);
    }
    int minDepth(TreeNode* root) {
        return getDepth(root);
    }
};
// 精简版
class Solution {
public:
    int minDepth(TreeNode* root) {
        if (root == nullptr) return 0;
        if (root->left == nullptr && root->right != nullptr) {
            return 1 + minDepth(root->right);
        }
        if (root->left != nullptr && root->right == nullptr) {
            return 1 + minDepth(root->left);
        }
        return 1 + min(minDepth(root->right), minDepth(root->left));
    }
};

// 迭代法——层序遍历
class Solution {
public:
    int minDepth(TreeNode* root) {
        int depth = 0;
        queue<TreeNode*> que;
        if (root != nullptr) que.push(root);
        while (!que.empty()) {
            depth++;
            int size = que.size();
            while (size--) {
                TreeNode* node = que.front();
                que.pop();
                if (node->left) que.push(node->left); // 左
                if (node->right) que.push(node->right);
                if (!node->left && !node->right) { // 当一层一层往下的时候,遇到第一个叶子结点即为最小深度
                    return depth;
                }
            }
        }
        return depth;
    }
};

222. 完全二叉树的节点个数

心得

题解

  • 完全二叉树的特点在于一定是由于若干满二叉树组成的,所以判断满二叉树直接用公式,非满二叉树用递归可减少计算复杂度由O(n)降到O(logn*logn)
  • 对于满二叉树的判断,只要遍历最左侧深度和最右侧深度一致即未满二叉树
  • 类似最大深度写法,后序遍历即可
// 获取普通二叉树个数——后序递归,时空O(n) O(logn)
class Solution {
public:
    int getNodesNum(TreeNode* cur) {
        if (cur == nullptr) return 0;
        int leftNums = getNodesNum(cur->left);
        int rightNums = getNodesNum(cur->right);
        return leftNums + rightNums + 1;
    }
    int countNodes(TreeNode* root) {
        return getNodesNum(root);
    }
};

// 完全二叉树定义——后序遍历
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; // 实际深度1,但是为下面指数计算方便
        while (left) { // 左子树深度
            left = left->left;
            leftDepth++;
        }
        while (right) {
            right = right->right; // 求右子树深度
            rightDepth++;
        }
        if (leftDepth == rightDepth) {
            return (2 << leftDepth) - 1; 
        }
        return countNodes(root->left) + countNodes(root->right) + 1;
    }
};