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

news2024/11/28 0:47:45

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、把二叉搜索树转换为累加树
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/646829.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

eslint + prettier如何搭配使用

简介 eslintprettier写代码爽到飞起&#xff0c;既规范了代码的格式&#xff0c;同时也让你的代码美观易读。本文介绍如何在项目中使用eslint搭配prettier来规范你的代码 1.eslint 和 prettier区别 先来回答一个问题&#xff0c;eslint和prettier这二者有啥区别&#xff0c;es…

【后端面经-数据库】MySQL的事务隔离级别简介

【后端面经-数据库】MySQL的事务隔离级别简介 0. 事务的概念1. 三类问题2. 事务隔离级别3. 操作指令4. 总结5. 参考博文 0. 事务的概念 事务指的是一连串的集中操作指令&#xff0c;一个事务的执行必须执行完所有的动作才能算作执行结束。事务具有四个特点&#xff0c;简记作A…

表示学习(Representation Learning) Part2--Auto-Encoders、VAEs、GANs

文章目录 Compression:Auto-EncodersCapture parameter distribution (variance): Variational Auto-Encoders原理介绍数学推导生成数据diffusion modelsPros&Cons Train using a second network: GANs 来自Manolis Kellis教授&#xff08;MIT计算生物学主任&#xff09;的…

spark_idea

spark_idea 3、打jar包运行2、code1、pom_xml0、创建数据、模型、预测表0、Windows配置scala环境 3、打jar包运行 ./bin/spark-submit \--class spark02 \--master spark://hadoop102:7077 \--deploy-mode client \/home/gpb/scala_spark2.jar打jar包、存储到虚拟机中 编写执行…

什么是布隆过滤器?如何解决高并发缓存穿透问题?

日常开发中&#xff0c;大家经常使用缓存&#xff0c;但是你知道大型的互联网公司面对高并发流量&#xff0c;要注意缓存穿透问题吗!!! 本文会介绍布隆过滤器&#xff0c;空间换时间&#xff0c;以较低的内存空间、高效解决这个问题。 本篇文章的目录&#xff1a; 1、性能不…

IMX6ULL裸机篇之SPI实验-ICM20608代码实现

一. SPI 实验 SPI实验&#xff1a;学习如何使用 I.MX6U 的 SPI 接口来驱动 ICM-20608&#xff0c;读取 ICM-20608 的六轴数据。 本文学习 SPI通信实验中&#xff0c;涉及从设备的 SPI代码编写。 之前学习了 SPI 主控芯片代码的编写&#xff0c;如下所示&#xff1a; IMX6ULL…

【ROS】RViz使用详解

1、安装 1.1 ROS1-RVIZ RVIZ的ROS1各个ubuntu版本中的安装命令 ubuntu14.04&#xff1a; sudo apt install ros-indigo-rvizubuntu16.04&#xff1a; sudo apt install ros-kinetic-rvizubuntu18.04&#xff1a; sudo apt install ros-melodic-rvizubuntu20.04&#xff1a…

Java厘米级高精准定位系统源码(支持UWB、蓝牙、WIFI定位)

高精准定位系统支持10厘米工业级高精准定位&#xff0c;同时支持UWB&#xff0c;蓝牙&#xff0c;WIFI定位。 ♦高精准定位系统首页为数据统计页面&#xff0c;统计的信息可以分为数量统计、区域告警人数统计、工牌使用量的统计、区域报警率统计以及告警消息的展示。 系统首页…

Pytest教程__常用执行参数详解(3)

前面讲了测试用例的执行方式&#xff0c;也认识了 -v -s 这些参数&#xff0c;那么还有没有其它参数呢&#xff1f;答案肯定是有的&#xff0c;我们可以通过 pytest -h来查看所有可用参数。 从图中可以看出&#xff0c;pytest的参数有很多&#xff0c;但并不是每一个参数都需要…

fiddler高级工具栏中的statistics数据分析工具

Fiddler statistics 板块会统计一个请求开始发出到最终接收并转发的数据&#xff0c;统计和响应的一些信息&#xff1a; 可以使用statistics分页&#xff0c;完成简单的性能测试&#xff0c;查看其接口的响应时间 如图展示&#xff1a; 如图详细解释下每一项的含义&#xff…

grep(General Regular Expression Parser)命令

基本用法 本篇介绍非常有用的命令是grep&#xff0c;这个不寻常的名字代表的是通用正则表达式解析器&#xff08;General Regular Expression Parser&#xff0c;简写为grep&#xff09;。你使用find命令在系统中搜索文件&#xff0c;而使用grep命令在文件中搜索字符串。事实上…

磁盘坏道:sd 2:0:0:0: [sda] Sense Key : Medium Error [current] [descriptor]

现网问题 从log来看磁盘可能存在问题&#xff0c;进一步实锤。 问题定位 通过badblocks扫描磁盘&#xff0c;发现sda磁盘有磁道损坏&#xff0c;建议更换磁盘。 badblocks命令详解 Linux badblocks命令用于检查磁盘装置中损坏的区块,执行指令时须指定所要检查的磁盘装置&…

postman高级使用

概念&#xff1a;让程序代替人判断测试用例执行的结果是否符合预期的一个过程 特点&#xff1a; postman断言使用js编写&#xff0c;断言写在postman的tests中 tests脚本在发送请求之后执行&#xff0c;会把断言的结果最终在testresult中进行展示 常用的postman提供的断言片…

在Django项目中的各个应用中分别编写路由配置文件urls.py

目录 01-通过命令建立三个应用02-配置路由 /index/、/app1/index/、/app2/index/02-1-配置路由 /index/ 并将各个应用的urls.py文件包含进主路由目录中02-02-配置路由/app1/index/02-03-配置路由/app2/index/ 03-编写各个应用的视图views.py 文件04-注册模板文件所在目录05 创建…

CVPR23 | 可编辑3D场景布局的文本引导多对象合成NeRF

来源&#xff1a;投稿 作者&#xff1a;橡皮 编辑&#xff1a;学姐 论文链接&#xff1a;https://arxiv.org/abs/2303.13843 0.背景&#xff1a; 最近&#xff0c;文本到图像生成通过将视觉-语言预训练模型与扩散模型相结合&#xff0c;取得了巨大的成功。这些突破也使得强大…

python: read excel and export excel

""" PythonAppReadExcel.py edit&#xff1a; geovindu,Geovin Du,涂聚文 date 2023-06-13 保险 """ # This is a sample Python script. # python.exe -m pip install --upgrade pip # Press ShiftF10 to execute it or replace it with your c…

orbslam 地图点观测距离范围 mfMinDistance,mfMaxDistance 的理解

目的是在不同帧不同距离的范围内观测到同一个地图点 直观理解&#xff0c;由于相机成像小孔成像近大远小 相机在距离特征点i 1米时图像金字塔第0层的 31x31图像区域&#xff0c; 类似于相机在距离 特征点i 最远约米时的图像金字塔第7层的31x31图像区域。 相机在距离特征点i 1…

桥接模式(十)

不管怎么样&#xff0c;都要继续充满着希望 上一章简单介绍了适配器模式(九), 如果没有看过, 请观看上一章 一. 桥接模式 引用 菜鸟教程里面的 桥接模式介绍: https://www.runoob.com/design-pattern/bridge-pattern.html 桥接&#xff08;Bridge&#xff09;是用于把抽象化…

GitHub 2800颗星,支持GPT/Transformer,字节跳动这个开源项目是怎么来的?

AI 绘画、机器翻译、多轮对话……对于各类 AI 相关的功能来说&#xff0c;总有一个痛点&#xff0c;困扰着所有训模型的算法工程师们&#xff1a; 想要效果更好&#xff0c;那么 AI 模型一般都很大&#xff0c;耗费的算力更多不说&#xff0c;运行起来还更费时间&#xff1b; 如…

关键字static,final的使用

关键字&#xff1a;static 概念 是java中的一个关键字 用于修饰成员&#xff08;成员变量和成员方法&#xff09; 类属性、类方法的设计思想 概念&#xff1a; 当我们编写一个类时&#xff0c;其实就是在描述其对象的属性和行为&#xff0c;而并没有产生实 质上的对象&#x…