代码随想录算法训练营第16天 | 104.二叉树的最大深度、559.n叉树的最大深度、111.二叉树的最小深度、222.完全二叉树的节点个数

发布于 2022-12-02  496 次阅读


104. 二叉树的最大深度 - 力扣(LeetCode)

思路:层序遍历二叉树,每遍历一层深度就加一

我的AC代码

// 时间复杂度O(n),空间复杂度O(n)
class Solution {
public:
    int maxDepth(TreeNode* root) {
        queue<TreeNode*> que;
        int depth = 0;
        if(root == nullptr) {
            return depth;
        }
        que.push(root);
        while(!que.empty()) {
            ++depth;
            int qsize = que.size();
            while(qsize--) {
                TreeNode* tmp = que.front();
                que.pop();
                if(tmp->left) {
                    que.push(tmp->left);
                }
                if(tmp->right) {
                    que.push(tmp->right);
                }
            }
        }
        return depth;
    }
};

标准答案

递归法(后序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class solution {
public:
    int getdepth(treenode* node) {
        if (node == NULL) return 0;
        int leftdepth = getdepth(node->left);       // 左
        int rightdepth = getdepth(node->right);     // 右
        int depth = 1 + max(leftdepth, rightdepth); // 中
        return depth;
    }
    int maxdepth(treenode* root) {
        return getdepth(root);
    }
};

递归法(前序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class solution {
public:
    int result;
    void getdepth(treenode* node, int depth) {
        result = depth > result ? depth : result; // 中

        if (node->left == NULL && node->right == NULL) return ;

        if (node->left) { // 左
            depth++;    // 深度+1
            getdepth(node->left, depth);
            depth--;    // 回溯,深度-1
        }
        if (node->right) { // 右
            depth++;    // 深度+1
            getdepth(node->right, depth);
            depth--;    // 回溯,深度-1
        }
        return ;
    }
    int maxdepth(treenode* root) {
        result = 0;
        if (root == NULL) return result;
        getdepth(root, 1);
        return result;
    }
};

迭代法(层序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class solution {
public:
    int maxdepth(treenode* root) {
        if (root == NULL) return 0;
        int depth = 0;
        queue<treenode*> que;
        que.push(root);
        while(!que.empty()) {
            int size = que.size();
            depth++; // 记录深度
            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 叉树的最大深度 - 力扣(LeetCode)

思路:与二叉树的最大深度思路一致,只是这次不是找左右子树的最大值,而是找所有子树中的最大值

我的AC代码

递归法(后序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class Solution {
public:
    int getDepth(Node* node) {
        if(node == nullptr) {
            return 0;
        }
        int mmax = 0;
        for(auto a : node->children) {
            if(a) {
              mmax = max(mmax, getDepth(a));  
            }
        }
        return mmax + 1;
    }
    int maxDepth(Node* root) {
        if(root == nullptr) {
            return 0;
        }
        return getDepth(root);
    }
};

递归法(前序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class Solution {
public:
    int results = 0;
    void getDepth(Node* node, int depth) {
        results = max(results, depth);
        for(auto a : node->children) {
            if(a) {
                getDepth(a, depth + 1);
            }
        }
        return;
    }
    int maxDepth(Node* root) {
        if(root == nullptr) {
            return 0;
        }
        getDepth(root, 1);
        return results;
    }
};

迭代法(层序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class Solution {
public:
    int maxDepth(Node* root) {
        queue<Node*> que;
        if(root ==nullptr) {
            return 0;
        }
        que.push(root);
        int depth = 0;
        while(!que.empty()) {
            depth++;
            int qsize = que.size();
            while(qsize--) {
                Node* tmp = que.front();
                que.pop();
                for(auto a : tmp->children) {
                    if(a) {
                        que.push(a);
                    }
                }
            }
        }
        return depth;
    }
};

标准答案

递归法(后序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class solution {
public:
    int maxdepth(node* root) {
        if (root == 0) return 0;
        int depth = 0;
        for (int i = 0; i < root->children.size(); i++) {
            depth = max (depth, maxdepth(root->children[i]));
        }
        return depth + 1;
    }
};

迭代法(层序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class solution {
public:
    int maxdepth(node* root) {
        queue<node*> que;
        if (root != NULL) que.push(root);
        int depth = 0;
        while (!que.empty()) {
            int size = que.size();
            depth++; // 记录深度
            for (int i = 0; i < size; i++) {
                node* node = que.front();
                que.pop();
                for (int j = 0; j < node->children.size(); j++) {
                    if (node->children[j]) que.push(node->children[j]);
                }
            }
        }
        return depth;
    }
};

111. 二叉树的最小深度 - 力扣(LeetCode)

思路:层序遍历二叉树,如果遇到左右子树都为空的节点,即刻返回此时的深度

我的AC代码

递归法(前序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class Solution {
public:
    int getDepth(TreeNode* node, int depth) {
        int a, b;
        if(node->left == nullptr && node->right == nullptr) {
            return depth;
        }
        if(node->left) {
            a = getDepth(node->left, depth + 1);
        }
        if(node->right) {
            b = getDepth(node->right, depth + 1);
        }
        return min(a, b);
    }
    int minDepth(TreeNode* root) {
        if(root == nullptr) {
            return 0;
        }
        return getDepth(root, 1);;
    }
};

递归法(后序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class Solution {
public:
    int getDepth(TreeNode* node) {
        if(node == nullptr) {
            return 0;
        }
        int left = getDepth(node->left);
        int right = getDepth(node->right);
        if(node->left == nullptr && node->right) {
            return 1 + right;
        }
        if(node->right == nullptr && node->left) {
            return 1 + left;
        }
        return 1 + min(left, right);
    }
    int minDepth(TreeNode* root) {
        return getDepth(root);
    }
};

迭代法(层序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class Solution {
public:
    int minDepth(TreeNode* root) {
        queue<TreeNode*> q;
        int ans = 0;
        if(root == nullptr) {
            return ans;
        }
        q.push(root);
        while(!q.empty()) {
            ans++;
            int qsize = q.size();
            while(qsize--) {
                TreeNode* tmp = q.front();
                q.pop();
                int flag = 0;
                if(tmp->left) {
                      q.push(tmp->left);
                }
                else {
                    flag++;
                }
                if(tmp->right) {
                      q.push(tmp->right);
                }
                else {
                    if(flag == 1) {
                        return ans;
                    }
                }
            }
        }
        return ans;
    }
};

标准答案

递归法(前序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class Solution {
private:
    int result;
    void getdepth(TreeNode* node, int depth) {
        if (node->left == NULL && node->right == NULL) {
            result = min(depth, result);  
            return;
        }
        // 中 只不过中没有处理的逻辑
        if (node->left) { // 左
            getdepth(node->left, depth + 1);
        }
        if (node->right) { // 右
            getdepth(node->right, depth + 1);
        }
        return ;
    }

public:
    int minDepth(TreeNode* root) {
        if (root == NULL) return 0;
        result = INT_MAX;
        getdepth(root, 1);
        return result;
    }
};

递归法(后序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class Solution {
public:
    int getDepth(TreeNode* node) {
        if (node == NULL) return 0;
        int leftDepth = getDepth(node->left);           // 左
        int rightDepth = getDepth(node->right);         // 右
                                                        // 中
        // 当一个左子树为空,右不为空,这时并不是最低点
        if (node->left == NULL && node->right != NULL) { 
            return 1 + rightDepth;
        }   
        // 当一个右子树为空,左不为空,这时并不是最低点
        if (node->left != NULL && node->right == NULL) { 
            return 1 + leftDepth;
        }
        int result = 1 + min(leftDepth, rightDepth);
        return result;
    }

    int minDepth(TreeNode* root) {
        return getDepth(root);
    }
};

迭代法(层序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class Solution {
public:

    int minDepth(TreeNode* root) {
        if (root == NULL) return 0;
        int depth = 0;
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty()) {
            int size = que.size();
            depth++; // 记录最小深度
            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);
                if (!node->left && !node->right) { // 当左右孩子都为空的时候,说明是最低点的一层了,退出
                    return depth;
                }
            }
        }
        return depth;
    }
};

222. 完全二叉树的节点个数 - 力扣(LeetCode)

思路:迭代法的思路是层序遍历二叉树,每遇到一个节点就计数加一。前序遍历递归法的思路是返回左子树和右子树所有节点个数并且加上当前节点的个数(1)。利用满二叉树的性质的做法是每递归到一个节点,不断找该节点的左右孩子,如果该节点左右子树的深度一样,说明是个满二叉树,可以直接利用公式计算,如果不是满二叉树,则用普通二叉树的方式计算,这种做法大大减少了空间复杂度和时间复杂度

我的AC代码

递归法(后序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class Solution {
public:
    int countNodes(TreeNode* root) {
        if(root == nullptr) {
            return 0;
        }
        return 1 + countNodes(root->left) + countNodes(root->right);
    }
};

迭代法(层序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class Solution {
public:
    int countNodes(TreeNode* root) {
        int ans = 0;
        queue<TreeNode*> que;
        if(root == nullptr) {
            return 0;
        }
        que.push(root);
        while(!que.empty()) {
            int qsize = que.size();
            while(qsize--) {
                TreeNode* tmp = que.front();
                que.pop();
                ans++;
                if(tmp->left) {
                    que.push(tmp->left);
                }
                if(tmp->right) {
                    que.push(tmp->right);
                }
            }
        }
        return ans;
    }
};

递归法(利用满二叉树的性质)

// 时间复杂度:O(log n × log n), 空间复杂度:O(log n)
class Solution {
public:
    int getall(TreeNode* node) {
        if(node == nullptr) {
            return 0;
        }
        int left, right;
        int k = 1;
        TreeNode* cur1 = node;
        TreeNode* cur2 = node;
        while(cur1->left && cur2->right) {
            k++;
            cur1 = cur1->left;
            cur2 = cur2->right;
            if(!cur1 && !cur2) {
                return pow(2, k) - 1;
            }
        }
        left = getall(node->left);
        right = getall(node->right);
        return 1 + left + right;
    }
    int countNodes(TreeNode* root) {
        return getall(root);
    }
};

标准答案

递归法(前序遍历)

// 时间复杂度O(n),空间复杂度O(n)
// 版本一
class Solution {
private:
    int getNodesNum(TreeNode* cur) {
        if (cur == NULL) return 0;
        int leftNum = getNodesNum(cur->left);      // 左
        int rightNum = getNodesNum(cur->right);    // 右
        int treeNum = leftNum + rightNum + 1;      // 中
        return treeNum;
    }
public:
    int countNodes(TreeNode* root) {
        return getNodesNum(root);
    }
};
// 版本二
class Solution {
public:
    int countNodes(TreeNode* root) {
        if (root == NULL) return 0;
        return 1 + countNodes(root->left) + countNodes(root->right);
    }
};

迭代法(层序遍历)

// 时间复杂度O(n),空间复杂度O(n)
class Solution {
public:
    int countNodes(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) 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();
                result++;   // 记录节点数量
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return result;
    }
};

递归法(利用满二叉树的性质)

// 时间复杂度:O(log n × log n),空间复杂度:O(log n)
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<<1) 相当于2^2,所以leftDepth初始为0
        }
        return countNodes(root->left) + countNodes(root->right) + 1;
    }
};