跟着《代码随想录刷题》(六)—— 二叉树

这篇具有很好参考价值的文章主要介绍了跟着《代码随想录刷题》(六)—— 二叉树。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

6.1 二叉树的前、中、后序遍历

144.、二叉树的前序遍历(中左右)

LeetCode:114、二叉树的前序遍历
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

(1)递归法

class Solution {
public:
    void traversal(TreeNode* cur, vector<int>& vec) {
        if (cur == NULL) return;
        vec.push_back(cur->val);    // 中
        traversal(cur->left, vec);  // 左
        traversal(cur->right, vec); // 右
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);
        return result;
    }
};

(2)迭代法

class Solution {
public:
    // 迭代法
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> result;

        if (root == NULL) return result;
        st.push(root);
        
        while (!st.empty()) {
            TreeNode* node = st.top();                // 中
            st.pop();
            result.push_back(node->val);
            if (node->right) st.push(node->right);   // 右(空节点不入栈)
            if (node->left) st.push(node->left);    // 左(空节点不入栈)
        }
        return result;
    }
};

(3)统一迭代格式

class Solution {
public:
    // 统一的迭代格式
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> st;
        if (NULL == root)
            return res;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop();
                if (node->right) st.push(node->right); // 右
                if (node->left) st.push(node->left);  // 左
                st.push(node);  // 中
                st.push(NULL);
            } else {
                st.pop();
                node = st.top();
                st.pop();
                res.push_back(node->val);
            }
        }
        return res;
    }
};

94、二叉树的中序遍历(左中右)

LeetCode:94、二叉树的中序遍历

(1)递归法

class Solution {
public:
    void traversal(TreeNode* cur, vector<int>& vec) {
        if (cur == NULL)
            return;

        traversal(cur->left, vec);
        vec.push_back(cur->val);
        traversal(cur->right, vec);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);

        return result;
    }
};

(2)迭代法

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        
        while (cur != NULL || !st.empty()) {
            if (cur != NULL) { // 指针来访问节点,访问到最底层
                st.push(cur); // 将访问的节点放进栈
                cur = cur->left;             // 左
            } else {
                cur = st.top(); // 从栈里弹出的数据,就是要处理的数据(放进result数组里的数据)
                st.pop();
                result.push_back(cur->val);   // 中
                cur = cur->right;             // 右
            }
        }
        return result;
    }
};

(3)统一迭代格式

class Solution {
public:
    // 统一迭代格式
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> st;
        if (NULL == root)
            return res;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop();
                if (node->right) st.push(node->right); // 右
                st.push(node); // 中
                st.push(NULL);
                if (node->left) st.push(node->left); // 左
            } else {
                st.pop();
                node = st.top();
                st.pop();
                res.push_back(node->val);
            }
        }
        return res;
    }
};

145、二叉树的后序遍历(左右中)

LeetCode:145、二叉树的后序遍历

(1)递归法

class Solution {
public:
    void traversal(TreeNode* cur, vector<int>& vec) {
        if (cur == NULL) 
            return;

        traversal(cur->left, vec); // 左
        traversal(cur->right, vec); // 右
        vec.push_back(cur->val); // 中
    }
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);
        
        return result;
    }
};

(2)迭代法

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> result;
        if (root == NULL) return result;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            st.pop();
            result.push_back(node->val);
            if (node->left) st.push(node->left); // 空节点不入栈
            if (node->right) st.push(node->right); // 空节点不入栈
        }
        reverse(result.begin(), result.end()); // 将结果反转之后就是左右中的顺序了
        return result;
    }
};

(3)统一迭代格式

class Solution {
public:
    // 统一迭代格式
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> st;
        if (NULL == root)
            return res;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop();
                st.push(node); // 中
                st.push(NULL);
                if (node->right) st.push(node->right); // 右
                if (node->left) st.push(node->left); // 左
            } else {
                st.pop();
                node = st.top();
                st.pop();
                res.push_back(node->val);
            }
        }
        return res;
    }
};

589、N叉树前序遍历

LeetCode:589、N叉树前序遍历

跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

class Solution {
public:
    void traversal(Node* cur, vector<int>& vec) {
        if (NULL == cur) return;
        vec.push_back(cur->val);

        for (int i = 0; i < cur->children.size(); i++) {
            traversal(cur->children[i], vec);
        }
    }
    vector<int> preorder(Node* root) {
        vector<int> res;
        traversal(root, res);
        return res;
    }
};

590、N叉树的后序遍历

LeetCode:590、N叉树的后序遍历

跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

class Solution {
public:
    // 递归
    void traversal(Node* cur, vector<int>& vec) {
        if (NULL == cur) return;
        for (int i = 0; i < cur->children.size(); i++) {
            traversal(cur->children[i], vec);
        }
        
        vec.push_back(cur->val);
    }

    vector<int> postorder(Node* root) {
        vector<int> res;
        traversal(root, res);
        return res;
    }
};

6.2 二叉树的层序遍历

102、二叉树的层序遍历

LeetCode:102、二叉树的层序遍历

跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> result;
        queue<TreeNode*> que;
        if (NULL == root)
            return result;
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            vector<int> cur;
            // 这里一定要使用固定的大小的size,不要使用que.size()
            // 因为que.size()是在不断变化的
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                cur.push_back(node->val);
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            result.push_back(cur);
        }

        return result;
    }
};

107、二叉树的层序遍历 II

LeetCode:107、二叉树的层序遍历||

跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        vector<vector<int>> res;
        queue<TreeNode*> que;
        if (NULL == root) return res;
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            vector<int> vec;
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                vec.push_back(node->val);
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            res.push_back(vec);
        }
        reverse(res.begin(), res.end()); // 在这里翻转一下即可
        return res;
    }
};

637、二叉树的层平均值

LeetCode:637、二叉树的层平均值

跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        vector<double> res;
        queue<TreeNode*> que;
        if (NULL == root)
            return res;
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            double sum = 0; // // 统计每⼀层的和
            for(int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                sum += node->val;
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            res.push_back(sum / size); // 将每⼀层均值放进结果集
        }
        return res;
    }
};

429、N 叉树的层序遍历

LeetCode:N叉树的层序遍历

跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        vector<vector<int>> res;
        queue<Node*> que;
        if (NULL == root)
            return res;
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            vector<int> vec;
            for (int i = 0; i < size; i++) {
                Node* node = que.front();
                que.pop();
                vec.push_back(node->val);
                for (int i = 0; i < node->children.size(); i++) {
                    if (node->children[i]) que.push(node->children[i]);
                }
            }
            res.push_back(vec);
        }
        return res;
    }
};

515、在每个树行中找最大值

LeetCode:515、在每个树行中找最大值

跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

class Solution {
public:
    vector<int> largestValues(TreeNode* root) {
        vector<int> res;
        queue<TreeNode*> que;
        if (NULL == root) return res;
        que.push(root);
        
        while (!que.empty()) {
            int size = que.size();
            int max = INT_MIN;

            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();

                max = max > (node->val) ? max : node->val;
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            res.push_back(max);
        }
        return res;
    }
};

116、填充每个节点的下一个右侧节点指针

LeetCode:116、填充每个节点的下一个右侧节点指针

跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

class Solution {
public:
    Node* connect(Node* root) {
        queue<Node*> que;
        if (NULL == root) return root;
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            Node* nodePre;
            Node* node;

            for (int i = 0; i < size; i++) {
                if (0 == i) {
                    nodePre = que.front(); // 取出⼀层的头结点
                    que.pop();
                    node = nodePre; // 这一行不能少
                } else {
                    node = que.front();
                    que.pop();
                    nodePre->next = node;  // 本层前⼀个节点next指向本节点
                    nodePre = node; // 这里有点类似双指针的感觉
                }

                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            nodePre->next = NULL; // 本层最后⼀个节点指向NULL
        }
        return root;
    }
};

117、填充每个节点的下一个右侧节点指针 II

LeetCode:117、填充每个节点的下一个右侧节点指针 ||
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

class Solution {
public:
    Node* connect(Node* root) {
        queue<Node*> que;
        if (NULL == root) return root;
        que.push(root);

        while (!que.empty()) {
            int size = que.size();
            Node* nodePre;
            Node* node;

            for (int i = 0; i < size; i++) {
                if (0 == i) {
                    nodePre = que.front();
                    que.pop();
                    node = nodePre;
                } else {
                    node = que.front();
                    que.pop();
                    nodePre->next = node;
                    nodePre = node;
                }

                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            nodePre->next = NULL;
        }
        return root;
    }
};

6.3 翻转二叉树

226、翻转二叉树

LeetCode:226、翻转二叉树

跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

(1)基于前序-递归

class Solution {
public:
    // 基于前序遍历的递归法
    void swapTree(TreeNode* cur) {
        if (NULL == cur) 
            return;
        
        swap(cur->left, cur->right); // 中
        swapTree(cur->left); // 左
        swapTree(cur->right); // 右
    }

    TreeNode* invertTree(TreeNode* root) {
        swapTree(root);
        return root;
    }
};

(2)基于前序-迭代

class Solution {
public:
    // 基于前序遍历的迭代法
    TreeNode* invertTree(TreeNode* root) {
        stack<TreeNode*> st;
        if (NULL == root)
            return root;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            st.pop();
            swap(node->left, node->right); // 中
            if (node->right) st.push(node->right); // 右
            if (node->left) st.push(node->left); // 左
        }

        return root;
    }
};

(3)基于层序遍历

class Solution {
public:
    // 层序遍历
    TreeNode* invertTree(TreeNode* root) {
        queue<TreeNode*> que;
        if (NULL == root) return root;
        que.push(root);

        while (!que.empty()) {
            int size = que.size();

            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();

                swap(node->left, node->right);
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return root;
    }
};
  • 注意:其实这里不用 for 循环也能翻转成功,因为我们不必要求把元素一层一层的堆放起来。我们只是一层一层的访问(…只可意会吧…)
class Solution {
public:
    // 层序遍历
    TreeNode* invertTree(TreeNode* root) {
        queue<TreeNode*> que;
        if (NULL == root) return root;
        que.push(root);

        while (!que.empty()) {
            TreeNode* node = que.front();
            que.pop();

            swap(node->left, node->right);
            if (node->left) que.push(node->left);
            if (node->right) que.push(node->right);
        }
        return root;
    }
};

6.4 对称二叉树

101、对称二叉树

LeetCode:101、对称二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

(1)递归法

class Solution {
public:
    bool compare(TreeNode* left, TreeNode* right) {
        // 首先排除空节点的情况
        if (left == NULL && right != NULL) return false;
        else if (left != NULL && right == NULL) return false;
        else if (left == NULL && right == NULL) return true;
        // 排除了空节点,再排除数值不相同的情况
        else if (left->val != right->val) return false;
        else {
            // 此时就是:左右节点都不为空,且数值相同的情况
            // 此时才做递归,做下一层的判断
            bool outside = compare(left->left, right->right); // 左子树:左、 右子树:右
            bool inside = compare(left->right, right->left);  // 左子树:右、 右子树:左
            bool isSame = outside && inside;      // 左子树:中、 右子树:中 (逻辑处理)
            return isSame;
        }
    }
    
    bool isSymmetric(TreeNode* root) {
        if (root == NULL) return true;
        return compare(root->left, root->right);
    }
};

(2)迭代法 - 队列

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        queue<TreeNode*> que;
        if (NULL == root) return true;
        // 注意:这里加入队列一定是成对加入的
        // 所以在加入队列前,一定不要判断 是否为空,否则会出现不成对的情况
        // 下面也一样
        que.push(root->left); // 将左子树头结点加入队列
        que.push(root->right); // 将右子树头结点加入队列

        while (!que.empty()) {
            TreeNode* leftNode = que.front(); que.pop();
            TreeNode* rightNode = que.front(); que.pop();

            if (leftNode == NULL && rightNode == NULL) continue;
            else if (leftNode != NULL && rightNode == NULL) return false;
            else if (leftNode == NULL && rightNode != NULL) return false;
            else if (leftNode->val != rightNode->val) return false;
            else {
                que.push(leftNode->left); // 加入左节点左孩子
                que.push(rightNode->right); // 加入右节点右孩子
                que.push(leftNode->right); // 加入左节点右孩子
                que.push(rightNode->left); // 加入右节点左孩子
            }
        }
        return true;
    }
};

(3)迭代法 - 栈

基本和上面一样

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        stack<TreeNode*> st;
        if (NULL == root) return true;
        st.push(root->left);
        st.push(root->right);

        while (!st.empty()) {
            TreeNode* rightNode = st.top(); st.pop();
            TreeNode* leftNode = st.top(); st.pop();

            if (leftNode == NULL && rightNode == NULL) continue;
            else if (leftNode != NULL && rightNode == NULL) return false;
            else if (leftNode == NULL && rightNode != NULL) return false;
            else if (leftNode->val != rightNode->val) return false;
            else {
                st.push(leftNode->left);
                st.push(rightNode->right);
                st.push(leftNode->right);
                st.push(rightNode->left);
            }
        }
        return true;
    }
};

100、相同的树

LeetCode:100.相同的树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

  • 递归法
class Solution {
public:
    // 递归
    bool compareTree(TreeNode* left, TreeNode* right) {
        if (left == NULL && right == NULL) return true;
        else if (left != NULL && right == NULL) return false;
        else if (left == NULL && right != NULL) return false;
        else if (left->val != right->val) return false;
        else {
            bool res_left = compareTree(left->left, right->left);
            bool res_right = compareTree(left->right, right->right);
            return res_left && res_right;
        }
    }

    bool isSameTree(TreeNode* p, TreeNode* q) {
        return compareTree(p, q);
    }
};

572、另一棵树的子树

LeetCode:572、另一棵树的子树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

class Solution {
public:
    bool isSame(TreeNode* left, TreeNode* right) {
        if (left == NULL && right == NULL) return true;
        else if (left != NULL && right == NULL) return false;
        else if (left == NULL && right != NULL) return false;
        else if (left->val != right->val) return false;
        else {
            bool resLeft = isSame(left->left, right->left);
            bool resRight = isSame(left->right, right->right);
            return resLeft && resRight;
        }
    }


    bool isSubtree(TreeNode* root, TreeNode* subRoot) {
        if (root == NULL) return false;

        if (isSame(root, subRoot)) return true;

        return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
    }
};

6.5 二叉树的最大深度

104、二叉树的最大深度

LeetCode:104、二叉树的最大深度
跟着《代码随想录刷题》(六)—— 二叉树

(1)基于后序遍历的递归法

class Solution {
public:
    // 递归 基于后序遍历(左右中)
    int getHeight(TreeNode* node) {
        if (NULL == node) return 0;

        int leftHeight = getHeight(node->left);
        int rightHeight = getHeight(node->right);
        int height = 1 + max(leftHeight, rightHeight);

        return height;
    }
    int maxDepth(TreeNode* root) {
        return getHeight(root);
    }
};

(2)基于层序遍历

class Solution {
public:
    int maxDepth(TreeNode* root) {
        queue<TreeNode*> que;
        int depth = 0;
        if (NULL == root) return 0;
        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:559、N叉树的最大深度

跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

(1)基于后序遍历的递归法

class Solution {
public:
    int getDepth(Node* node) {
        if (NULL == node) return 0;
        int depth = 0;
        for (int i = 0; i < node->children.size(); i++) {
            depth = max(depth, getDepth(node->children[i]));
        }
        return depth + 1;
    }
    int maxDepth(Node* root) {
        return getDepth(root);
    }
};

(2)基于层序遍历

class Solution {
public:
    int maxDepth(Node* root) {
        queue<Node*> que;
        int depth = 0;
        if (NULL == root) return 0;
        que.push(root);
        
        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++) {
                    que.push(node->children[j]);
                }
            }
        }
        return depth;
    }
};

6.6 二叉树的最小深度

111、二叉树的最小深度

LeetCode:111.二叉树的最小深度
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

(1)基于后序遍历

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);
    }
};

(2)基于层序遍历

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;
    }
};

6.7 完全二叉树的节点个数

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

LeetCode:222.完全二叉树的节点个数
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

(1)当作普通二叉树:后序遍历递归

class Solution {
public:
    // 当作普通二叉树来计算节点:后序递归
    int getNum(TreeNode* node) {
        if (node == NULL) return 0;

        int leftNum = getNum(node->left);
        int rightNum = getNum(node->right);

        return 1 + leftNum + rightNum;
    }
    
    int countNodes(TreeNode* root) {
        return getNum(root);
    }
};

(2)当作普通二叉树:层序遍历

class Solution {
public:
    int countNodes(TreeNode* root) {
        int depth = 0;
        queue<TreeNode*> que;
        if (NULL == root)
            return 0;
        que.push(root);

        while (!que.empty()) {
            int size = que.size();

            for (int i = 0; i < size; i++) {
                depth++;
                TreeNode* node = que.front();
                que.pop();

                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return depth;
    }
};

(3)利用满二叉树的特性

class Solution {
public:
    int getNum(TreeNode* node) {
        if (node == NULL) return 0;

        TreeNode* leftNode = node->left;
        TreeNode* rightNode = node->right;
        // 这里初始为0是有目的的,为了下面求指数方便
        int leftheight = 0, rightheight = 0;

        while (leftNode) {// 求左子树深度
            leftNode = leftNode->left;
            leftheight++;
        }
        while (rightNode) {// 求右子树深度
            rightNode = rightNode->right;
            rightheight++;
        }
        // 注意(2<<1) 相当于2^2,所以leftheight初始为0
        if (leftheight == rightheight)
            return (2 << leftheight) - 1;

        leftheight = getNum(node->left);
        rightheight = getNum(node->right);

        return 1 + leftheight + rightheight;
    }
    int countNodes(TreeNode* root) {
        return getNum(root);
    }
};

6.8 平衡二叉树

110、平衡二叉树

LeetCode:110.平衡二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

  • 基于后序遍历判断左右子树高度差是否大于1
class Solution {
public:
    // 基于后序遍历
    int getHeight(TreeNode* node) {
        if (NULL == node) return 0;
        // 左
        int leftHeight = getHeight(node->left);
        if (-1 == leftHeight) return -1;
        // 右
        int rightHeight = getHeight(node->right);
        if (-1 == rightHeight) return -1;
        // 中
        if (abs(leftHeight - rightHeight) > 1) 
            return -1;
        else 
            return 1 + max(leftHeight, rightHeight);
    }

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

6.9 二叉树的所有路径

257、二叉树的所有路径

LeetCode:257.二叉树的所有路径

跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

(1)基于前序遍历的递归法

class Solution {
private:

    void traversal(TreeNode* cur, vector<int>& path, vector<string>& result) {
        path.push_back(cur->val); // 中,中为什么写在这里,因为最后一个节点也要加入到path中 
        // 这才到了叶子节点
        if (cur->left == NULL && cur->right == NULL) {
            string sPath;
            for (int i = 0; i < path.size() - 1; i++) {
                // to_string()函数:括号内的 数字 转化为 字符串
                sPath += to_string(path[i]);
                sPath += "->";
            }
            sPath += to_string(path[path.size() - 1]);
            result.push_back(sPath);
            return;
        }
        if (cur->left) { // 左 
            traversal(cur->left, path, result);
            path.pop_back(); // 回溯
        }
        if (cur->right) { // 右
            traversal(cur->right, path, result);
            path.pop_back(); // 回溯
        }
    }

public:
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> result;
        vector<int> path;
        if (root == NULL) return result;
        traversal(root, path, result);
        return result;
    }
};

6.10 左叶子之和

404、左叶子之和

LeetCode:404.左叶子之和

跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

(1)基于后序遍历的递归法

class Solution {
public:
    int traversal(TreeNode* node) {
        if (node == NULL) return 0;
        if (node->left == NULL && node->right == NULL) return 0;

        int leftNum = traversal(node->left);
        if (node->left != NULL && node->left->left == NULL && node->left->right == NULL)
            leftNum = node->left->val;

        int rightNum = traversal(node->right);

        return leftNum + rightNum;
    }
    int sumOfLeftLeaves(TreeNode* root) {
        return traversal(root);
    }
};

(2)基于前序遍历的迭代法

class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        int result = 0;
        stack<TreeNode*> st;

        if (NULL == root) return 0;
        st.push(root);

        while (!st.empty()) {
            TreeNode* node = st.top();
            st.pop();

            if (node->left != NULL && node->left->left == NULL && node->left->right == NULL)
                result += node->left->val;

            if(node->right) st.push(node->right);
            if (node->left) st.push(node->left);
        }
        return result;
    }
};

(3)基于层序遍历法

class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        int result = 0;
        queue<TreeNode*> que;
        if (NULL == root) return 0;
        que.push(root);

        while (!que.empty()) {
            int size = que.size();

            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();

                if (node->left != NULL && node->left->left == NULL && node->left->right == NULL)
                    result += node->left->val;

                if (node->left)  que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return result;
    }
};

6.11 找树左下角的值

513、找树左下角的值

LeetCode:513、找树左下角的值

跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

(1)递归法

class Solution {
public:
    int maxDepth = INT_MIN;
    int result;
    void traversal(TreeNode* root, int depth) {
        if (root->left == NULL && root->right == NULL) {
            if (depth > maxDepth) {
                maxDepth = depth;
                result = root->val;
            }
            return;
        }
        if (root->left) {
            depth++;
            traversal(root->left, depth);
            depth--; // 回溯
        }
        if (root->right) {
            depth++;
            traversal(root->right, depth);
            depth--; // 回溯
        }
        return;
    }
    int findBottomLeftValue(TreeNode* root) {
        traversal(root, 0);
        return result;
    }
};

(2)基于层序遍历

class Solution {
public:
    int findBottomLeftValue(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();
                if (i == 0) result = node->val; // 记录最后一行第一个元素
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return result;
    }
};

6.12 路径总和

112、路径总和

LeetCode:112.路径总和
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

(1)基于《二叉树所有路径》进行修改

class Solution {
public:
    int res = -1;
    void traversal(TreeNode* node, vector<int>& path, int& targetSum) {
        path.push_back(node->val);
        if (node->left == NULL && node->right == NULL) {
            int sum = 0;
            for (int i = 0; i < path.size(); i++) {
                sum += path[i];
            }
            if (sum == targetSum) {
                res = 1;
                return;
            }

        }

        if (node->left) {
            traversal(node->left, path, targetSum);
            path.pop_back();
        }

        if (node->right) {
            traversal(node->right, path, targetSum);
            path.pop_back();
        }
    }
    bool hasPathSum(TreeNode* root, int targetSum) {
        vector<int> path;
        if (NULL == root)
            return false;
        traversal(root, path, targetSum);
        return res == 1 ? true : false;
    }
};

(2)递归法

class Solution {
private:
    bool traversal(TreeNode* cur, int count) {
        if (!cur->left && !cur->right) 
            return count == 0;  // 遇到叶子节点,判断计数器是否为0

        if (cur->left) { // 左
            count -= cur->left->val; // 递归,处理节点;
            if (traversal(cur->left, count)) return true;
            count += cur->left->val; // 回溯,撤销处理结果
        }
        if (cur->right) { // 右
            count -= cur->right->val; // 递归,处理节点;
            if (traversal(cur->right, count)) return true;
            count += cur->right->val; // 回溯,撤销处理结果
        }
        return false;
    }

public:
    bool hasPathSum(TreeNode* root, int sum) {
        if (root == NULL) return false;
        // 这里一定要减掉root节点的值
        return traversal(root, sum - root->val);
    }
};

(3)基于前序遍历的迭代法

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        stack<pair<TreeNode*, int>> st;
        if (NULL == root) return false;
        st.push(pair<TreeNode*, int>(root, root->val));

        while (!st.empty()) {
            pair<TreeNode*, int> pari_node = st.top();
            st.pop();
            TreeNode* node = pari_node.first;
            int val = pari_node.second;

            if (node->left == NULL && node->right == NULL) {
                if (val == targetSum)
                    return true;
                else 
                    continue;
            }

            if (node->left) 
                st.push(pair<TreeNode*, int>(node->left, val + node->left->val));
            if (node->right) 
                st.push(pair<TreeNode*, int>(node->right, val + node->right->val));       
        }

        return false;
    }
};

113、路径总和 II

LeetCode:113.路径总和 II
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

(1)基于《二叉树所有路径》修改

class Solution {
public:
    void traversal(TreeNode* node, int targetSum, vector<int>& path, vector<vector<int>>& result) {
        path.push_back(node->val);
        if (node->left == NULL && node->right == NULL) {
            int sum = 0;
            for (int i = 0; i < path.size(); i++) {
                sum += path[i];
            }

            if (sum == targetSum) 
                result.push_back(path);
            return;
        }

        if (node->left) {
            traversal(node->left, targetSum, path, result);
            path.pop_back();
        }

        if (node->right) {
            traversal(node->right, targetSum, path, result);
            path.pop_back();
        }
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        vector<int> path;
        vector<vector<int>> result;
        if (root == NULL) return result;
        traversal(root, targetSum, path, result);
        return result;
    }
};

(2)迭代法

class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;

    void traversal(TreeNode* node, int count) {
        path.push_back(node->val);
        if (node->left == NULL && node->right == NULL) {
            if (count == 0) 
                result.push_back(path);
            return;
        }

        if (node->left) {
            count -= node->left->val;
            traversal(node->left, count);
            count += node->left->val;
            path.pop_back();
        }

        if (node->right) {
            count -= node->right->val;
            traversal(node->right, count);
            count += node->right->val;
            path.pop_back();
        }
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        if (root == NULL) return result;
        traversal(root, targetSum - root->val);
        return result;
    }
};

6.13 从中序和后序遍历构造二叉树

106、从中序和后序遍历序列构造二叉树

LeetCode:106、从中序和后序遍历序列构造二叉树

跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

  • 完整版
class Solution {
private:
    TreeNode* traversal (vector<int>& inorder, vector<int>& postorder) {
        if (postorder.size() == 0) return NULL;

        // 后序遍历数组最后一个元素,就是当前的中间节点
        int rootValue = postorder[postorder.size() - 1];
        TreeNode* root = new TreeNode(rootValue);

        // 叶子节点
        if (postorder.size() == 1) return root;

        // 找到中序遍历的切割点
        int delimiterIndex;
        for (delimiterIndex = 0; delimiterIndex < inorder.size(); delimiterIndex++) {
            if (inorder[delimiterIndex] == rootValue) break;
        }

        // 切割中序数组
        // 左闭右开区间:[0, delimiterIndex)
        vector<int> leftInorder(inorder.begin(), inorder.begin() + delimiterIndex);
        // [delimiterIndex + 1, end)
        vector<int> rightInorder(inorder.begin() + delimiterIndex + 1, inorder.end() );

        // postorder 舍弃末尾元素
        postorder.resize(postorder.size() - 1);

        // 切割后序数组
        // 依然左闭右开,注意这里使用了左中序数组大小作为切割点
        // [0, leftInorder.size)
        vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());
        // [leftInorder.size(), end)
        vector<int> rightPostorder(postorder.begin() + leftInorder.size(), postorder.end());

        root->left = traversal(leftInorder, leftPostorder);
        root->right = traversal(rightInorder, rightPostorder);

        return root;
    }
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if (inorder.size() == 0 || postorder.size() == 0) return NULL;
        return traversal(inorder, postorder);
    }
};
  • 精简版
class Solution {
private:
    // 中序区间:[inorderBegin, inorderEnd),后序区间[postorderBegin, postorderEnd)
    TreeNode* traversal (vector<int>& inorder, int inorderBegin, int inorderEnd, 
                        vector<int>& postorder, int postorderBegin, int postorderEnd) {
        if (postorderBegin == postorderEnd) return NULL;

        int rootValue = postorder[postorderEnd - 1];
        TreeNode* root = new TreeNode(rootValue);

        if (postorderEnd - postorderBegin == 1) return root;

        int delimiterIndex;
        for (delimiterIndex = inorderBegin; delimiterIndex < inorderEnd; delimiterIndex++) {
            if (inorder[delimiterIndex] == rootValue) break;
        }
        // 切割中序数组
        // 左中序区间,左闭右开[leftInorderBegin, leftInorderEnd)
        int leftInorderBegin = inorderBegin;
        int leftInorderEnd = delimiterIndex;
        // 右中序区间,左闭右开[rightInorderBegin, rightInorderEnd)
        int rightInorderBegin = delimiterIndex + 1;
        int rightInorderEnd = inorderEnd;

        // 切割后序数组
        // 左后序区间,左闭右开[leftPostorderBegin, leftPostorderEnd)
        int leftPostorderBegin =  postorderBegin;
        int leftPostorderEnd = postorderBegin + delimiterIndex - inorderBegin; // 终止位置是 需要加上 中序区间的大小size
        // 右后序区间,左闭右开[rightPostorderBegin, rightPostorderEnd)
        int rightPostorderBegin = postorderBegin + (delimiterIndex - inorderBegin);
        int rightPostorderEnd = postorderEnd - 1; // 排除最后一个元素,已经作为节点了

        root->left = traversal(inorder, leftInorderBegin, leftInorderEnd,  
                                postorder, leftPostorderBegin, leftPostorderEnd);
        root->right = traversal(inorder, rightInorderBegin, rightInorderEnd, 
                                postorder, rightPostorderBegin, rightPostorderEnd);

        return root;
    }
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if (inorder.size() == 0 || postorder.size() == 0) return NULL;
        // 左闭右开的原则
        return traversal(inorder, 0, inorder.size(), postorder, 0, postorder.size());
    }
};

105、从前序与中序遍历序列构造二叉树

LeetCode:105、从前序与中序遍历序列构造二叉树

跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

  • 完整版
class Solution {
public:
    TreeNode* traversal(vector<int> preorder, vector<int> inorder) {
        if (preorder.size() == 0) return NULL;
        int val = preorder[0];
        TreeNode* root = new TreeNode(val);
        if (preorder.size() == 1) return root;

        int index;
        for (index = 0; index < inorder.size(); index++) {
            if (inorder[index] == val)
                break;
        }

        vector<int> leftInorder(inorder.begin(), inorder.begin() + index);
        vector<int> rightInorder(inorder.begin() + index + 1, inorder.end());

        vector<int> leftPreorder(preorder.begin() + 1, preorder.begin() + 1 + index);
        vector<int> rightPreorder(preorder.begin() + 1 + index, preorder.end());

        root->left = traversal(leftPreorder, leftInorder);
        root->right = traversal(rightPreorder, rightInorder);

        return root;
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if (preorder.size() == 0 || inorder.size() == 0) return NULL;
        return traversal(preorder, inorder);
    }
};
  • 精简版
class Solution {
public:
    TreeNode* traversal(vector<int>& preorder, int preorderBegin, int preorderEnd,
                        vector<int>& inorder, int inorderBegin, int inorderEnd) {
        if (preorderEnd == preorderBegin) return NULL;
        int val = preorder[preorderBegin];
        TreeNode* root = new TreeNode(val);
        if (preorderEnd - preorderBegin == 1) return root;

        int index;
        for (index = inorderBegin; index < inorderEnd; index++) {
            if (inorder[index] == val)
                break;
        }

        int leftInorderBegin = inorderBegin;
        int leftInorderEnd = index; 

        int rightInorderBegin = index + 1;
        int rightInorderEnd = inorderEnd;

        int leftPreorderBegin = preorderBegin + 1;
        int leftPreorderEnd = leftPreorderBegin + leftInorderEnd - leftInorderBegin;

        int rightPreorderBegin = leftPreorderEnd;
        int rightPreorderEnd = preorderEnd;

        root->left = traversal(preorder, leftPreorderBegin, leftPreorderEnd,
                                inorder, leftInorderBegin, leftInorderEnd);
        root->right = traversal(preorder, rightPreorderBegin, rightPreorderEnd,
                                inorder, rightInorderBegin, rightInorderEnd);
        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if (preorder.size() == 0 || inorder.size() == 0) return NULL;
        return traversal(preorder, 0, preorder.size(), inorder, 0, inorder.size());
    }
};

6.14 最大二叉树

654、最大二叉树

LeetCode:654、最大二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

(1)完整版

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        TreeNode* node = new TreeNode(0);
        if (nums.size() == 1) {
            node->val = nums[0];
            return node;
        }
        // 找到数组中最大的值和对应的下标
        int maxValue = 0;
        int maxValueIndex = 0;
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] > maxValue) {
                maxValue = nums[i];
                maxValueIndex = i;
            }
        }
        node->val = maxValue;
        // 最大值所在的下标左区间 构造左子树
        if (maxValueIndex > 0) {
            vector<int> newVec(nums.begin(), nums.begin() + maxValueIndex);
            node->left = constructMaximumBinaryTree(newVec);
        }
        // 最大值所在的下标右区间 构造右子树
        if (maxValueIndex < (nums.size() - 1)) {
            vector<int> newVec(nums.begin() + maxValueIndex + 1, nums.end());
            node->right = constructMaximumBinaryTree(newVec);
        }
        return node;
    }
};

(2)精简版

class Solution {
private:
    // 在左闭右开区间[left, right),构造二叉树
    TreeNode* traversal(vector<int>& nums, int left, int right) {
        if (left >= right) return nullptr;

        // 分割点下标:maxValueIndex
        int maxValueIndex = left;
        for (int i = left + 1; i < right; ++i) {
            if (nums[i] > nums[maxValueIndex]) maxValueIndex = i;
        }

        TreeNode* root = new TreeNode(nums[maxValueIndex]);

        // 左闭右开:[left, maxValueIndex)
        root->left = traversal(nums, left, maxValueIndex);

        // 左闭右开:[maxValueIndex + 1, right)
        root->right = traversal(nums, maxValueIndex + 1, right);

        return root;
    }
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return traversal(nums, 0, nums.size());
    }
};

6.15 合并二叉树

617、合并二叉树

LeetCode:617、合并二叉树

跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

(1)基于前序遍历

class Solution {
public:
    // 基于前序遍历好理解
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        if (t1 == NULL) return t2; // 如果t1为空,合并之后就应该是t2
        if (t2 == NULL) return t1; // 如果t2为空,合并之后就应该是t1
        // 修改了t1的数值和结构
        t1->val += t2->val;                             // 中
        t1->left = mergeTrees(t1->left, t2->left);      // 左
        t1->right = mergeTrees(t1->right, t2->right);   // 右
        return t1;
    }
};

(2)新建一个二叉树

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        if (t1 == NULL) return t2;
        if (t2 == NULL) return t1;

        // 重新定义新的节点,不修改原有两个树的结构
        TreeNode* root = new TreeNode(0);
        root->val = t1->val + t2->val;

        root->left = mergeTrees(t1->left, t2->left);
        root->right = mergeTrees(t1->right, t2->right);
        
        return root;
    }
};

6.16 二叉搜索树中的搜索

700、二叉搜索树中的搜索

LeetCode:700、二叉搜索树中的搜索
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

(1)递归法

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        if(root == NULL || root->val == val) return root;

        TreeNode* node = NULL;
        if (val < root->val) node = searchBST(root->left, val);
        if (val > root->val) node = searchBST(root->right, val);

        return node;
    }
};

(2)迭代法

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        while (root != NULL) {
            if (val < root->val) root = root->left;
            else if (val > root->val) root = root->right;
            else return root;
        }
        return NULL;
    }
};

6.17 验证二叉搜索树

98、验证二叉搜索树

LeetCode:98、验证二叉搜索树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

(1)直白的解法:中序遍历,得到的数组升序

class Solution {
private:
    vector<int> vec;
    void traversal(TreeNode* root) {
        if (root == NULL) return;
        traversal(root->left);
        vec.push_back(root->val); // 将二叉搜索树转换为有序数组
        traversal(root->right);
    }
public:
    bool isValidBST(TreeNode* root) {
        vec.clear(); // 不加这句在leetcode上也可以过,但最好加上
        traversal(root);
        for (int i = 1; i < vec.size(); i++) {
            // 注意要小于等于,搜索树里不能有相同元素
            if (vec[i] <= vec[i - 1]) return false;
        }
        return true;
    }
};

(2)用maxValue来保存上一个节点的值

class Solution {
public:
    long long maxVal = LONG_MIN; // 因为后台测试数据中有int最小值
    bool isValidBST(TreeNode* root) {
        if (root == NULL) return true;

        bool left = isValidBST(root->left);
        // 中序遍历,验证遍历的元素是不是从小到大
        if (maxVal < root->val) maxVal = root->val;
        else return false;
        bool right = isValidBST(root->right);

        return left && right;
    }
};

(3)用pre来记录上一个节点的信息

class Solution {
public:
    TreeNode* pre = NULL; // 用来记录前一个节点
    bool isValidBST(TreeNode* root) {
        if (root == NULL) return true;
        bool left = isValidBST(root->left);

        if (pre != NULL && pre->val >= root->val) return false;
        pre = root; // 记录前一个节点

        bool right = isValidBST(root->right);
        return left && right;
    }
};

6.18 二叉搜索树的最小绝对差

530、二叉搜索树的最小绝对差

LeetCode:530、二叉搜索树的最小绝对差
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

(1)直观的做法:先中序遍历,再比较

class Solution {
private:
vector<int> vec;
void traversal(TreeNode* root) {
    if (root == NULL) return;
    traversal(root->left);
    vec.push_back(root->val); // 将二叉搜索树转换为有序数组
    traversal(root->right);
}
public:
    int getMinimumDifference(TreeNode* root) {
        vec.clear();
        traversal(root);
        if (vec.size() < 2) return 0;
        int result = INT_MAX;
        for (int i = 1; i < vec.size(); i++) { // 统计有序数组的最小差值
            result = min(result, vec[i] - vec[i-1]);
        }
        return result;
    }
};

(2)双指针法

class Solution {
private:
int result = INT_MAX;
TreeNode* pre = NULL;
void traversal(TreeNode* cur) {
    if (cur == NULL) return;
    traversal(cur->left);   // 左
    if (pre != NULL){       // 中
        result = min(result, cur->val - pre->val);
    }
    pre = cur; // 记录前一个
    traversal(cur->right);  // 右
}
public:
    int getMinimumDifference(TreeNode* root) {
        traversal(root);
        return result;
    }
};

6.19 二叉搜索树中的众数

501、二叉搜索树中的众数

LeetCode:501.二叉搜索树中的众数
跟着《代码随想录刷题》(六)—— 二叉树

双指针法

class Solution {
public:
    TreeNode* pre = NULL;
    int count = 0, maxCount = 0;
    vector<int> res;

    void traversal(TreeNode* cur) {
        if (cur == NULL) return;

        traversal(cur->left);

        if (pre == NULL) count = 1;
        else if (cur->val == pre->val) count++;
        else count = 1;
        pre = cur;

        if (count == maxCount) res.push_back(cur->val);
        else if (count > maxCount) {
            res.clear();
            res.push_back(cur->val);
            maxCount = count;
        }

        traversal(cur->right);
    }
    vector<int> findMode(TreeNode* root) {
        traversal(root);
        return res;
    }
};

6.20 二叉树的最近公共祖先

236、二叉树的最近公共祖先

LeetCode:236、二叉树的最近公共祖先
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root == NULL || root == p || root == q) return root;
       
        TreeNode* leftNode = lowestCommonAncestor(root->left, p, q);
        TreeNode* rightNode = lowestCommonAncestor(root->right, p, q);

        if (leftNode != NULL && rightNode != NULL) return root;
        else if (leftNode == NULL && rightNode != NULL) return rightNode;
        else if (leftNode != NULL && rightNode == NULL) return leftNode;
        else return NULL;
    }
};

6.21 二叉搜索树的最近公共祖先

235、二叉搜索树的最近公共祖先

LeetCode:235、二叉搜索树的最近公共祖先
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

  • 递归法
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root->val > p->val && root->val > q->val) {
            return lowestCommonAncestor(root->left, p, q);
        } else if (root->val < p->val && root->val < q->val) {
            return lowestCommonAncestor(root->right, p, q);
        } else return root;
    }
};
  • 迭代法
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        while(root) {
            if (root->val > p->val && root->val > q->val) {
                root = root->left;
            } else if (root->val < p->val && root->val < q->val) {
                root = root->right;
            } else return root;
        }
        return NULL;
    }
};

6.22 二叉搜索树中的插入操作

701、二叉搜索树中的插入操作

LeetCode:701、二叉搜索树中的插入操作
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

  • 递归法
class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if (root == NULL) {
            TreeNode* node = new TreeNode(val);
            return node;
        }

        if (val < root->val) 
            root->left = insertIntoBST(root->left, val);
        else 
            root->right = insertIntoBST(root->right, val);
        
        return root;
    }
};
  • 迭代法
class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if (root == NULL) {
            TreeNode* node = new TreeNode(val);
            return node;
        }
        TreeNode* cur = root;
        TreeNode* parent = root; // 这个很重要,需要记录上一个节点,否则无法赋值新节点
        while (cur != NULL) {
            parent = cur;
            if (cur->val > val) cur = cur->left;
            else cur = cur->right;
        }
        TreeNode* node = new TreeNode(val);
        if (val < parent->val) parent->left = node;// 此时是用parent节点的进行赋值
        else parent->right = node;
        return root;
    }
};

6.23 删除二叉搜索树中的节点

450、删除二叉搜索树中的节点

LeetCode:450、删除二叉搜索树中的节点
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

  • 删除节点分五种情况
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == NULL) return root; // 第一种情况:没找到删除的节点,遍历到空节点直接返回了
        if (root->val == key) {
            // 第二种情况:左右孩子都为空(叶子节点),
            // 直接删除节点, 返回NULL为根节点
            if (root->left == NULL && root->right == NULL) {
                ///! 内存释放
                delete root;
                return NULL;
            }
            // 第三种情况:其左孩子为空,右孩子不为空,
            // 删除节点,右孩子补位 ,返回右孩子为根节点
            else if (root->left == NULL) {
                TreeNode* retNode = root->right;
                ///! 内存释放
                delete root;
                return retNode;
            }
            // 第四种情况:其右孩子为空,左孩子不为空,
            // 删除节点,左孩子补位,返回左孩子为根节点
            else if (root->right == NULL) {
                TreeNode* retNode = root->left;
                ///! 内存释放
                delete root;
                return retNode;
            }
            // 第五种情况:左右孩子节点都不为空,
            //则将删除节点的左子树放到删除节点的右子树的最左面节点的左孩子的位置
            // 并返回删除节点右孩子为新的根节点。
            else {
                TreeNode* cur = root->right; // 找右子树最左面的节点
                while(cur->left != NULL) {
                    cur = cur->left;
                }
                cur->left = root->left; // 把要删除的节点(root)左子树放在cur的左孩子的位置
                TreeNode* tmp = root;   // 把root节点保存一下,下面来删除
                root = root->right;     // 返回旧root的右孩子作为新root
                delete tmp;             // 释放节点内存(这里不写也可以,但C++最好手动释放一下吧)
                return root;
            }
        }
        if (root->val > key) root->left = deleteNode(root->left, key);
        if (root->val < key) root->right = deleteNode(root->right, key);
        return root;
    }
};

6.24 修剪二叉搜索树

669、修剪二叉搜索树

LeetCode:669、修建二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

  • 递归法
class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        if (root == NULL) return root;

        if (root->val < low)
            return trimBST(root->right, low, high);
        else if (root->val > high)
            return trimBST(root->left, low, high);

        root->left = trimBST(root->left, low, high);
        root->right = trimBST(root->right, low, high);

        return root;
    }
};

6.25 将有序数组转换为二叉搜索树

108、将有序数组转换为二叉搜索树

LeetCode:108、将有序数组转换为二叉搜索树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树

  • 递归法
class Solution {
public:
    TreeNode* traversal(vector<int>& nums, int left, int right) {
        if (left > right) return NULL;
        int mid = left + ((right - left) / 2);
        TreeNode* root = new TreeNode(nums[mid]);
        root->left = traversal(nums, left, mid - 1);
        root->right = traversal(nums, mid + 1, right);
        return root;
    }
    
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return traversal(nums, 0, nums.size() - 1);
    }
};

6.26 把二叉搜索树转换为累加树

538、把二叉搜索树转换为累加树

LeetCode:538、把二叉搜索树转换为累加树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树
跟着《代码随想录刷题》(六)—— 二叉树文章来源地址https://www.toymoban.com/news/detail-483494.html

class Solution {
public:
    int pre =  0;
    void traversal(TreeNode* cur) {
        if (cur == NULL) return;
        traversal(cur->right);
        cur->val += pre;
        pre = cur->val;
        traversal(cur->left);
    }
    TreeNode* convertBST(TreeNode* root) {
        traversal(root);
        return root;
    }
};

到了这里,关于跟着《代码随想录刷题》(六)—— 二叉树的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 代码随想录二刷 |二叉树 | 二叉树的右视图

    199.二叉树的右视图 给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4] 示例 2: 输入: [1,null,3] 输出: [1,3] 示例 3: 输入: [] 输出: [] 提示: 二叉树的节点个数的范围是 [0,1

    2024年02月04日
    浏览(38)
  • 代码随想录day13 | 226.翻转二叉树 101.对称二叉树

    使用前、后序反转最为方便。 为啥不推荐中序? 中序遍历,某些节点的左右孩子会翻转两次,某些节点左右孩子不会被反转。 101.对称二叉树 关键在于,看这个节点对应的左子树和右子树是否可以相互反转。 1、如何比较呢? 比较的是两个子树的里侧和外侧的元素是否相等

    2024年02月15日
    浏览(29)
  • 1月3日代码随想录反转二叉树

    给你一棵二叉树的根节点  root  ,翻转这棵二叉树,并返回其根节点。 示例 1: 示例 2: 示例 3: 提示: 树中节点数目范围在  [0, 100]  内 -100 = Node.val = 100 这道题用递归的思想就是将根节点的左右儿子交换,然后再对子节点进行递归操作,直到子节点均为空。 但是我感觉

    2024年02月03日
    浏览(32)
  • 随想录刷题笔记 —二叉树篇3 117填充每个节点的下一个右侧节点指针II 104二叉树最大深度 111二叉树最小深度

    和116的区别在于116是完美二叉树,而117中的结点并非左右子结点都存在。 解法一:队列 解法二:双循环代替队列 解法一:队列 使用depth标记深度,进行层序遍历,每遍历完一层,depth+1 解法二:递归 递归出口:传入结点为空,返回0 否则返回左子结点和右子结点返回值的最

    2024年02月19日
    浏览(33)
  • 代码随想录day21(2)二叉树:二叉树的所有路径(leetcode257)

    题目要求:按任意顺序返回所有从根节点到叶节点的路径 思路:我们先递归地进行前序遍历,同时要注意回溯的过程,注意一些库的用法即可。 leetcode实战: 代码实现:

    2024年03月18日
    浏览(39)
  • 【Day22-慢就是快】代码随想录-二叉树-迭代遍历

    用迭代法实现二叉树的前后中序遍历。 递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中 ,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。 此时大家应该知道我们用栈

    2024年02月10日
    浏览(35)
  • 【代码随想录day21】二叉树的最近公共祖先

    给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。” 这题的难点在于: 如何建

    2024年02月15日
    浏览(34)
  • 代码随想录额外题目| 二叉树 ●129求根到叶数字之和 ●1382二叉树变平衡●100相同的树

    #129求根到叶数字之和 回溯放进vector,然后从后往前拿,乘1 10 100 ... 很基础的回溯 my code: 随想录跟我思路差不多,但这两个是放globa的:int result; vectorint path; 最近总觉得global不安全不想放  #1382二叉树变平衡 本来遇到这种会换root的就头疼,然后看了眼随想录,是要先变成

    2024年02月14日
    浏览(22)
  • 【代码随想录day19】从前序与中序遍历序列构造二叉树

    使用递归建树,流程如下: 取出后序节点创建新树的节点 找到新树的节点在中序中的索引 分割中序序列 分割后序序列 继续递归建立整颗新树

    2024年02月15日
    浏览(28)
  • 代码随想录Day12 二叉树 LeetCode T102二叉树的层序遍历 T226 翻转二叉树 T101 对称二叉树

    本文思路和详细讲解来自于:代码随想录 (programmercarl.com) 题目链接:102. 二叉树的层序遍历 - 力扣(LeetCode) 本题使用队列辅助完成,讲解主要函数CheckOrder:首先判断root是否为空,是就直接返回,然后创建队列,向里加入root元素,计算队列的长度,也就是每一层的元素个数,while循环,si

    2024年02月06日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包