算法学习|二叉树

学习材料声明

所有知识点都来自互联网,进行总结和梳理,侵权必删。
引用来源:基本参考代码随想录的刷题顺序和讲解。

理论基础

二叉树

1.1满二叉树(满!)和完全二叉树

满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。深度为k,有2^k-1个节点的二叉树。
完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层(h从1开始),则该层包含 1~ 2^(h-1) 个节点。

1.2二叉搜索树和平衡二叉树

在这里插入图片描述
在这里插入图片描述

1.3存储方式:顺序存储(数组)和链式存储(链表)

在考试过程中用数组比较好,因为链表一不小心就断了-。-||.
在这里插入图片描述
在这里插入图片描述

1.4遍历顺序:深度(前中后)和广度(层次)

因为求深度可以从上到下去查 所以需要前序遍历(中左右),而高度只能从下到上去查,所以只能后序遍历(左右中)

  • 深度优先遍历:(使用栈实现)
    前序遍历(递归法,迭代法)
    中序遍历(递归法,迭代法)
    后序遍历(递归法,迭代法)
  • 广度优先遍历:(使用队列实现)
    层次遍历(迭代法)

1.5链表二叉树的定义

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

1.6遍历实现(基于链表与递归)

前序遍历:

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

中序遍历:

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

后序遍历:

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

1.7遍历实现(基于链表与迭代:栈)

前序遍历:

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

中序遍历:

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

后序遍历:
在这里插入图片描述

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

1.8统一迭代框架

在这里插入图片描述

1.9层次遍历(借助队列)

出一个,进两个它的孩子。

习题

1遍历

1.1|144. 二叉树的前序遍历

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    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> vec;
        traversal(root, vec);
        return vec;
    }
};

1.2|145. 二叉树的后序遍历

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> vec;
        traversal(root, vec);
        return vec;
    }
};

1.3|94. 二叉树的中序遍历

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> vec;
        traversal(root, vec);
        return vec;

    }
};

2层次遍历及其变体

2.1|102. 二叉树的层序遍历

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        vector<vector<int>> result;
        while (!que.empty()) {
            int size = que.size();
            vector<int> vec;
            // 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的
            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);
            }
            result.push_back(vec);
        }
        return result;
    

    }
};

2.2|107. 二叉树的层序遍历 II

reverse(result.begin(), result.end());

2.3|199. 二叉树的右视图

class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        queue<TreeNode*> que;
        vector<int> result;
        if(root!=NULL){
            que.push(root);
        }
        while(!que.empty()){
            int size = que.size();
            int tmp;
            for(int i=1; i<=size; i++){
                TreeNode* node=que.front();
                que.pop();
                tmp = node->val;
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            result.push_back(tmp);
        }
        return result;
    }
};

2.4|637. 二叉树的层平均值

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        queue<TreeNode*> que;
        vector<double> result;
        if(root!=NULL){
            que.push(root);
        }
        while(!que.empty()){
            int size = que.size();
            double sum=0;
            for(int i=1; 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);
            }
            result.push_back(sum/(double)size);
        }
        return result;
    }
};

2.5|429. N 叉树的层序遍历

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

2.6|515. 在每个树行中找最大值

class Solution {
public:
    vector<int> largestValues(TreeNode* root) {
        queue<TreeNode*> que;
        vector<int> result;
        if(root!=NULL){
            que.push(root);
        }
        while(!que.empty()){
            int size = que.size();
            int maxn=INT_MIN;
            for(int i=1; i<=size; i++){
                TreeNode* node=que.front();
                que.pop();
                maxn = max(maxn, node->val);
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            result.push_back(maxn);
        }
        return result;
    }
};

2.7|116. 填充每个节点的下一个右侧节点指针

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

2.8|117. 填充每个节点的下一个右侧节点指针 II

和上一题没什么区别。除了原始二叉树,一个要求完全二叉树,本题不要求。

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

2.9|104. 二叉树的最大深度

class Solution {
public:
    int maxDepth(TreeNode* root) {
        queue<TreeNode*> que;
        int result=0;
        if(root!=NULL){
            que.push(root);
        }
        while(!que.empty()){
            int size = que.size();
            for(int i=1; i<=size; i++){
                TreeNode* node=que.front();
                que.pop();
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            result++;
        }
        return result;
    }
};

2.10|111. 二叉树的最小深度

class Solution {
public:
    int minDepth(TreeNode* root) {
        queue<TreeNode*> que;
        int result=0;
        if(root!=NULL){
            que.push(root);
            result++;
        }
        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->right==NULL){
                    return result;
                }
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            result++;
        }
        return result;
    }
};

3各种类型题目

3.1|226. 翻转二叉树

还是(前,后,层次)遍历的思路+交换左右儿子。

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

3.2|101. 对称二叉树

想了好多方法,总是有几个点过不去。
代码随想录里面是按照外层,内层,细节到位置对称节点本身位置,比较值。

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;

        // 此时就是:左右节点都不为空,且数值相同的情况
        // 此时才做递归,做下一层的判断
        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);
    }
};

3.3|对称二叉树变体100. 相同的树

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;

        // 此时就是:左右节点都不为空,且数值相同的情况
        // 此时才做递归,做下一层的判断
        bool outside = compare(left->left, right->left);   // 左子树:左、 右子树:左
        bool inside = compare(left->right, right->right);    // 左子树:右、 右子树:右
        bool isSame = outside && inside;                    // 左子树:中、 右子树:中 (逻辑处理)
        return isSame;

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

3.4|对称二叉树变体572. 另一棵树的子树

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;

        // 此时就是:左右节点都不为空,且数值相同的情况
        // 此时才做递归,做下一层的判断
        bool outside = compare(left->left, right->left);   // 左子树:左、 右子树:左
        bool inside = compare(left->right, right->right);    // 左子树:右、 右子树:右
        bool isSame = outside && inside;                    // 左子树:中、 右子树:中 (逻辑处理)
        return isSame;

    }
    bool isSubtree(TreeNode* root, TreeNode* subRoot) {
        stack<TreeNode*> stk;
        stk.push(root);
        while(!stk.empty()){
            TreeNode* node = stk.top();
            stk.pop();
            if(compare(node, subRoot)){
                return true;
            }
            if(node->left) stk.push(node->left);
            if(node->right) stk.push(node->right);
        }
        return false;
    }
};

3.5|完全二叉树的节点个数

这题就是遍历吧。

class Solution {
public:
    int sum=0;
    void traversal(TreeNode* cur) {
        if (cur == NULL) return;
        traversal(cur->left);  // 左
        sum++;
        traversal(cur->right); // 右
    }
    int countNodes(TreeNode* root) {
        traversal(root);
        return sum;
    }
};

或者左子树节点数+右子树节点数

// 版本一
class Solution {
private:
    int getNodesNum(TreeNode* cur) {
        if (cur == NULL) return 0;
        int leftNum = getNodesNum(cur->left);      // 左
        int rightNum = getNodesNum(cur->right);    // 右
        int treeNum = leftNum + rightNum + 1;      // 中
        return treeNum;
    }
public:
    int countNodes(TreeNode* root) {
        return getNodesNum(root);
    }
};

3.6|110. 平衡二叉树

自己琢磨出来的解法,但说实话,我也说不出什么逻辑。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int getHeight(TreeNode *cur){
        if(cur == NULL) return 0;
        return max(getHeight(cur->left), getHeight(cur->right))+1;
    }

    bool isBalanced(TreeNode* root){
        if(root == NULL){
            return true;
        }
        if(abs(getHeight(root->left) - getHeight(root->right)) <= 1){
            return isBalanced(root->left)&& isBalanced(root->right);
        }else{
            return false;
        }
    }
};

高度(后序遍历)

class Solution {
public:
    // 返回以该节点为根节点的二叉树的高度,如果不是平衡二叉树了则返回-1
    int getHeight(TreeNode* node) {
        if (node == NULL) {
            return 0;
        }
        int leftHeight = getHeight(node->left);
        if (leftHeight == -1) return -1;
        int rightHeight = getHeight(node->right);
        if (rightHeight == -1) return -1;
        return abs(leftHeight - rightHeight) > 1 ? -1 : 1 + max(leftHeight, rightHeight);
    }
    bool isBalanced(TreeNode* root) {
        return getHeight(root) == -1 ? false : true;
    }
};

3.7|257. 二叉树的所有路径

回溯法

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    string path;
    vector<string> ans;
    void camPaths(TreeNode* cur, bool isRoot){
        
        if(cur->left == NULL&&cur->right == NULL){
            if(isRoot){
            path = to_string(cur->val);
            }else{
                path = path + "->" + to_string(cur->val);
            }
            ans.push_back(path);
            cout<<path<<endl;
            return;
        }
        if(isRoot){
            path = to_string(cur->val);
        }else{
            path = path + "->" + to_string(cur->val);
        }
        cout<<path<<endl;
        string curpath = path;
        if(cur->left){
            camPaths(cur->left, false);
        }
        if(cur->right){
            path = curpath;
            camPaths(cur->right, false);
        }
        
    }
    vector<string> binaryTreePaths(TreeNode* root) {
        
        camPaths(root, true);
        return ans;
    }
};

代码随想录里的精简代码。

class Solution {
private:

    void traversal(TreeNode* cur, string path, vector<string>& result) {
        path += to_string(cur->val); // 中
        if (cur->left == NULL && cur->right == NULL) {
            result.push_back(path);
            return;
        }
        if (cur->left) traversal(cur->left, path + "->", result); // 左
        if (cur->right) traversal(cur->right, path + "->", result); // 右
    }

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

    }
};

3.8|404. 左叶子之和

还是比较简单的。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int sum=0;
    void camSumOfLeft(TreeNode* cur, bool isLeft){
        if(cur->left==NULL&&cur->right==NULL){
            if(isLeft){
                sum += cur->val;
            }
            return;
        }
        if(cur->left){    
            camSumOfLeft(cur->left, true);
        }
        if(cur->right){
            camSumOfLeft(cur->right, false);
        }
    }
    int sumOfLeftLeaves(TreeNode* root) {
        camSumOfLeft(root, false);
        return sum;
    }
};

代码随想录的思路,是分子树的感觉。

class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        if (root == NULL) return 0;
        int leftValue = 0;
        if (root->left != NULL && root->left->left == NULL && root->left->right == NULL) {
            leftValue = root->left->val;
        }
        return leftValue + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
    }
};

3.9|[513.找树左下角的值](https://leetcode.cn/problems/find-bottom-left-tree-value/)

先要满足最底层。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int ans;
    int maxDepth = 0;
    void searchAns(TreeNode* cur, int curDepth){
        if(cur->left==NULL&&cur->right==NULL){
            if(curDepth > maxDepth){
                ans = cur->val;
                maxDepth = curDepth;
            }
            return;
        }
        if(cur->left){
            searchAns(cur->left, curDepth+1);
        }
        if(cur->right){
            searchAns(cur->right, curDepth+1);
        }
    }
    int findBottomLeftValue(TreeNode* root) {
        searchAns(root, 1);
        return ans;
    }
};

代码随想录说,这题层次遍历是最好解决的了。

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

3.10|112. 路径总和

二叉树呀,你的本质就是回溯。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int result=0;
    bool ans = false;
    void traversal(TreeNode* cur, int sum, int target) {
        sum += cur->val; // 中
        if(ans){
            return;
        }
        if (cur->left == NULL && cur->right == NULL) {
            if(sum==target){
                ans = true;
            }
            return;
        }    
        if (cur->left) traversal(cur->left, sum, target); // 左
        if (cur->right) traversal(cur->right, sum, target); // 右
    }
    bool hasPathSum(TreeNode* root, int targetSum) {
        
        if (root == NULL) return ans;
        traversal(root, 0, targetSum);
        return ans;
        
    }
};

3.11|113. 路径总和 II

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> ans;
    vector<int> path;
    void traversal(TreeNode* cur, int sum, int target) {
        if (cur->left == NULL && cur->right == NULL) {
            if(sum==target){
                ans.push_back(path);
            }
            return;
        }    
        if (cur->left){
            sum += cur->left->val; 
            path.push_back(cur->left->val);
            traversal(cur->left, sum, target);
            sum -= cur->left->val;
            path.pop_back();

        }  // 左
        if (cur->right){
            sum += cur->right->val; 
            path.push_back(cur->right->val);
            traversal(cur->right, sum, target);
            sum -= cur->right->val;
            path.pop_back();
        }  // 右
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        ans.clear();
        path.clear();
        if (root == NULL) return ans;
        path.push_back(root->val);
        int sum = root->val;
        traversal(root, sum, targetSum);
        return ans;
    }
};

3.12|113. 路径总和 II

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> ans;
    vector<int> path;
    void traversal(TreeNode* cur, int sum, int target) {
        if (cur->left == NULL && cur->right == NULL) {
            if(sum==target){
                ans.push_back(path);
            }
            return;
        }    
        if (cur->left){
            sum += cur->left->val; 
            path.push_back(cur->left->val);
            traversal(cur->left, sum, target);
            sum -= cur->left->val;
            path.pop_back();

        }  // 左
        if (cur->right){
            sum += cur->right->val; 
            path.push_back(cur->right->val);
            traversal(cur->right, sum, target);
            sum -= cur->right->val;
            path.pop_back();
        }  // 右
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        ans.clear();
        path.clear();
        if (root == NULL) return ans;
        path.push_back(root->val);
        int sum = root->val;
        traversal(root, sum, targetSum);
        return ans;
    }
};

3.13|106. 从中序与后序遍历序列构造二叉树

这里涉及了陈年的老知识。

首先回忆一下如何根据两个顺序构造一个唯一的二叉树,相信理论知识大家应该都清楚,就是以 后序数组的最后一个元素为切割点,先切中序数组,根据中序数组,反过来再子数组的size切后序数组。一层一层切下去,每次后序数组最后一个元素就是节点元素。

没做出来,最后看得代码。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
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);
    }
};

3.14|105. 从前序与中序遍历序列构造二叉树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
private:
    TreeNode* traversal (vector<int>& preorder, vector<int>& inorder) {
        if (preorder.size() == 0) return NULL;

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

        // 叶子节点
        if (preorder.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() );
       
        // preorder 舍弃首元素
        preorder.erase(preorder.begin()+0);
       
        // 切割中序数组
        // 依然左闭右开,注意这里使用了左中序数组大小作为切割点
        // [0, leftInorder.size)
        vector<int> leftPreorder(preorder.begin(), preorder.begin() + leftInorder.size());
        // [leftInorder.size(), end)
        vector<int> rightPreorder(preorder.begin() + leftInorder.size(), preorder.end());

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

        return root;
    }
public:

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if (preorder.size() == 0 || inorder.size() == 0) return NULL;
        return traversal(preorder, inorder);
    }
};

3.15|654.最大二叉树

尽管题目已经给出了算法,但是还是花费了很久才搞清楚逻辑。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
   
    TreeNode* constructPoccess(vector<int>& nums, int l, int r){
        if(l>=r){
            return  nullptr;
        };
        TreeNode* cur = new TreeNode();
        int value = nums[l];
        int devideIdx = l;
        for(int i=l; i<r; i++){
            if(value<nums[i]){
                value = nums[i];
                devideIdx = i;
            }
        }
        cur->val = value;
        cur->left = constructPoccess(nums, l, devideIdx);
        cur->right = constructPoccess(nums, devideIdx+1, r);
        return cur;
    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        TreeNode* root = constructPoccess(nums, 0, nums.size());
        return root;
    }
};

3.16|617.合并二叉树

也还是比较简单的题,就是自己写得有点冗余。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* constructPoccess(TreeNode* cur1, TreeNode* cur2){
        if(cur1==nullptr && cur2== nullptr){
            return nullptr;
        }
        TreeNode* cur = new TreeNode();
        int value = 0;
        if(cur1!=nullptr && cur2== nullptr){
            cur->val += cur1->val;
            cur->left = constructPoccess(cur1->left, nullptr);
            cur->right = constructPoccess(cur1->right, nullptr);

        }
        if(cur1==nullptr && cur2!= nullptr){
            cur->val += cur2->val;
            cur->left = constructPoccess(nullptr, cur2->left);
            cur->right = constructPoccess(nullptr, cur2->right);
        }
        if(cur1!=nullptr && cur2!= nullptr){
            cur->val += cur1->val;
            cur->val += cur2->val;
            cur->left = constructPoccess(cur1->left, cur2->left);
            cur->right = constructPoccess(cur1->right, cur2->right);
        }     
        return cur;
    }
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        TreeNode* root = constructPoccess(root1, root2);
        return root;
    }
};

3.17|700.二叉搜索树中的搜索

也是很简单的一题。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        if(root == nullptr){
            return nullptr;
        }
        if(root->val > val){
            return searchBST(root->left, val);
        }
        if(root->val < val){
            return searchBST(root->right, val);
        }
        return root;
    }
};

3.18|98.验证二叉搜索树

思路有点乱,遇事不决先睡觉吧,是不是晕碳了??
怎么说呢,我是完全掉入陷阱了,忘记中序递增了。

陷阱1
不能单纯的比较左节点小于中间节点,右节点大于中间节点就完事了。
写出了类似这样的代码:

if (root->val > root->left->val && root->val < root->right->val) {
    return true;
} else {
    return false;
}

答案:

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

3.19|530.二叉搜索树的最小绝对差

分段的思路就是获取序列,然后再进行两次循环。
但是,这个是二叉树,中序遍历!一次循环!

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool isFirst=true;
    int preNum;
    int ans=INT_MAX;
    void getInOrder(TreeNode* cur){
        if(cur==nullptr){
            return;
        }
        getInOrder(cur->left);
        if(isFirst){
            preNum=cur->val;
            isFirst=false;
        }else{
            ans = min(ans, abs(cur->val-preNum));
            preNum = cur->val;
        }   
        getInOrder(cur->right);
    }
    int getMinimumDifference(TreeNode* root) {
        getInOrder(root);
        return ans;
    }
};

3.20|501.二叉搜索树中的众数

跟上题一样,就是遍历得到序列,然后像是序列一样处理找众数。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool isFirst=true;
    int preNum;
    int maxSum=0;
    vector<int> ans;
    int curSum=0;
    void getInOrder(TreeNode* cur){
        if(cur==nullptr){
            return;
        }
        getInOrder(cur->left);
        if(isFirst){
            curSum = 1;
            maxSum = 1;
            ans.clear();
            ans.push_back(cur->val);
            preNum = cur->val;
            isFirst=false;
        }else{
            if(cur->val==preNum){
                curSum++;
            }else{
                curSum=1;
            }
            if(curSum==maxSum){
                ans.push_back(cur->val);
            }
            if(curSum>maxSum){
                maxSum = curSum;
                ans.clear();
                ans.push_back(cur->val);
            }
            preNum = cur->val;
        }   
        getInOrder(cur->right);
    }
    vector<int> findMode(TreeNode* root) {
        getInOrder(root);
        return ans;
    }
};

3.21|236. 二叉树的最近公共祖先

我的做法就是找到p的路径,q的路径。
再根据两条路径找最近的公共祖先。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<TreeNode*> pPath, qPath;
    vector<TreeNode*> pAns, qAns;
    bool isFind=false;
    void findpPath(TreeNode* cur, TreeNode* p){
        if(isFind){
            return;
        }
        if(cur==nullptr){
            return;
        }
        if(cur==p){
            isFind = true;
            pAns.assign(pPath.begin(), pPath.end());
            return;
        }
        if(cur->left){
            pPath.push_back(cur->left);
            findpPath(cur->left, p);
            pPath.pop_back();
        }
        if(cur->right){
            pPath.push_back(cur->right);
            findpPath(cur->right, p);
            pPath.pop_back();
        }
    }
    void findqPath(TreeNode* cur, TreeNode* q){
        if(isFind){
            return;
        }
        if(cur==nullptr){
            return;
        }
        if(cur==q){
            isFind = true;
            qAns.assign(qPath.begin(), qPath.end());
            return;
        }
        if(cur->left){
            qPath.push_back(cur->left);
            findqPath(cur->left, q);
            qPath.pop_back();
        }
        if(cur->right){
            qPath.push_back(cur->right);
            findqPath(cur->right, q);
            qPath.pop_back();
        }
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        TreeNode* ans;
        pPath.push_back(root);
        findpPath(root, p);
        isFind = false;
        qPath.push_back(root);
        findqPath(root, q);
        cout<<pAns.size()<<" "<<qAns.size()<<endl;
        for(int i=0; i<pAns.size(); i++){
            cout<<pAns[i]->val<<" ";
        }
        cout<<endl;

        for(int  j=0; j<qAns.size(); j++){
            cout<<qAns[j]->val<<" ";
        }
        cout<<endl;
        for(int i=0, j=0; i<pAns.size()&&j<qAns.size(); i++,j++){
            if(pAns[i]==qAns[j]){
                ans = pAns[i];
            }
        }
        return ans;        
    }
};

代码随想录的思路显然更加高级。

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

        if (left == NULL && right != NULL) return right;
        else if (left != NULL && right == NULL) return left;
        else  { //  (left == NULL && right == NULL)
            return NULL;
        }

    }
};

3.22|235. 二叉搜索树的最近公共祖先

上一题肯定是可以解决的,但是还是要利用搜索树本身的性质更改搜索策略。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        TreeNode* mi;
        TreeNode* ma;
        if(p->val>q->val){
            mi=q;
            ma=p;
        }else{
            mi=p;
            ma=q;
        }
        if(root == p||root == q||root == nullptr) return root;

        if(root->val > mi->val && root->val < ma->val){
            return root;
        }
        if(root->val < mi->val){
            return lowestCommonAncestor(root->right, p, q);
        }
        if(root->val > ma->val){
            return lowestCommonAncestor(root->left, p, q);
        }  
        return root;   
    }
};

3.23|701.二叉搜索树中的插入操作

经常会断链表,啊啊啊啊。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void search(TreeNode* pre, TreeNode* cur, int val, bool isLeft) {
        if(cur==nullptr){
            if(isLeft)
                pre->left = new TreeNode(val);
            else
                pre->right = new TreeNode(val);
            return;
        }

        if(cur->val > val){
            search(cur, cur->left, val, true);
        }
        if(cur->val < val){
            search(cur, cur->right, val, false);
        }
    }
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if(root==nullptr){
            return new TreeNode(val);
        }
        search(root, root, val, false);
        return root;

    }
};

有返回值版本,我每次都会搞得乱七八糟。

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if (root == NULL) {
            TreeNode* node = new TreeNode(val);
            return node;
        }
        if (root->val > val) root->left = insertIntoBST(root->left, val);
        if (root->val < val) root->right = insertIntoBST(root->right, val);
        return root;
    }
};

3.24|450.删除二叉搜索树中的节点

写得很冗余,分了好几种可能,主要还是Pre这个不好操控,哈哈哈。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, TreeNode* tar) {
        if (root == NULL) {
            return tar;
        }
        if (root->val > tar->val) root->left = insertIntoBST(root->left, tar);
        if (root->val < tar->val) root->right = insertIntoBST(root->right, tar);
        return root;
    }
    TreeNode* Pre=nullptr;
    TreeNode* Tar=nullptr;
    bool isRight;
    void search(TreeNode* pre, TreeNode* cur, int val, bool isLeft) {
        if(cur==nullptr){
            return;
        }
        if(cur->val == val){
            Pre = pre;
            Tar = cur;
            isRight = !isLeft;
            return;
        }

        if(cur->val > val){
            search(cur, cur->left, val, true);
        }
        if(cur->val < val){
            search(cur, cur->right, val, false);
        }
    }
    TreeNode* deleteNode(TreeNode* root, int key) {
        search(root, root, key, false);
        if(Tar==nullptr){
            return root;
        }
        if(root->val == key){
            if(root->left==nullptr&&root->right==nullptr){
                return nullptr;    
            }else if(root->left!=nullptr&&root->right==nullptr){
                return root->left;
            }else if(root->left==nullptr&&root->right!=nullptr){
                return root->right;
            }else{
                root->right = insertIntoBST(root->right, root->left);
                return root->right;
            }
        }else{
            if(Tar->left==nullptr&&Tar->right==nullptr){
                if(isRight){
                    Pre->right = nullptr;
                }else{
                    Pre->left = nullptr;
                }
            }else if(Tar->left!=nullptr&&Tar->right==nullptr){
                if(isRight){
                    Pre->right = Tar->left;
                }else{
                    Pre->left = Tar->left;
                }
            }else if(Tar->left==nullptr&&Tar->right!=nullptr){
                if(isRight){
                    Pre->right = Tar->right;
                }else{
                    Pre->left = Tar->right;
                }
            }else{
                Tar->right = insertIntoBST(Tar->right, Tar->left);
                if(isRight){
                    Pre->right = Tar->right;
                }else{
                    Pre->left = Tar->right;
                }
            }
            
        }

        return root;
        
    }
};

代码随想录代码

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == nullptr) return root; // 第一种情况:没找到删除的节点,遍历到空节点直接返回了
        if (root->val == key) {
            // 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
            if (root->left == nullptr && root->right == nullptr) {
                ///! 内存释放
                delete root;
                return nullptr;
            }
            // 第三种情况:其左孩子为空,右孩子不为空,删除节点,右孩子补位 ,返回右孩子为根节点
            else if (root->left == nullptr) {
                auto retNode = root->right;
                ///! 内存释放
                delete root;
                return retNode;
            }
            // 第四种情况:其右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
            else if (root->right == nullptr) {
                auto retNode = root->left;
                ///! 内存释放
                delete root;
                return retNode;
            }
            // 第五种情况:左右孩子节点都不为空,则将删除节点的左子树放到删除节点的右子树的最左面节点的左孩子的位置
            // 并返回删除节点右孩子为新的根节点。
            else {
                TreeNode* cur = root->right; // 找右子树最左面的节点
                while(cur->left != nullptr) {
                    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;
    }
};

3.25|669. 修剪二叉搜索树

总是要处理第一个root发生错误,所以增加了一个head。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void doProcess(TreeNode* pre, TreeNode* cur, int low, int high, bool isLeft){
        cout<<cur->val<<endl;
        if(cur==nullptr){
            return;
        }   
        if(cur->val>high){
            if(isLeft){
                pre->left = cur->left;
                if(pre->left) doProcess(pre, pre->left, low, high, isLeft);
            }else{
                pre->right = cur->left;
                if(pre->right) doProcess(pre,pre->right, low, high, isLeft);
            }
        }else if(cur->val<low){
            if(isLeft){
                pre->left = cur->right;
                if(pre->left) doProcess(pre,pre->left, low, high, isLeft);
            }else{
                pre->right = cur->right;
                if(pre->right) doProcess(pre,pre->right, low, high, isLeft);
            }
        }else{
            pre = cur;
            if(cur->left) doProcess(pre, cur->left, low, high, true);
            if(cur->right) doProcess(pre, cur->right, low, high, false);
        }
       
        
    }
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        TreeNode* head = new TreeNode(low);
        head->left = root; 
        if(root==nullptr){
            return root;
        }
        doProcess(head, root, low, high, true);
        return head->left;
    }
};

代码随想录就简单很多。

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        if (root == nullptr ) return nullptr;
        if (root->val < low) {
            TreeNode* right = trimBST(root->right, low, high); // 寻找符合区间[low, high]的节点
            return right;
        }
        if (root->val > high) {
            TreeNode* left = trimBST(root->left, low, high); // 寻找符合区间[low, high]的节点
            return left;
        }
        root->left = trimBST(root->left, low, high); // root->left接入符合条件的左孩子
        root->right = trimBST(root->right, low, high); // root->right接入符合条件的右孩子
        return root;
    }
};

3.26|108.将有序数组转换为二叉搜索树

非常简单的递归。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        if(nums.size()==0){
            return nullptr;
        }
        int splitId = nums.size()/2;
        vector<int> numsLeft, numsRight;
        numsLeft.assign(nums.begin(), nums.begin()+splitId);
        numsRight.assign(nums.begin()+splitId+1, nums.end());
        TreeNode* cur = new TreeNode(nums[splitId]);
        cur->left = sortedArrayToBST(numsLeft);
        cur->right =  sortedArrayToBST(numsRight);
        return cur;

    }
};

3.27|538.把二叉搜索树转换为累加树

粗暴地想法就是遍历两次。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int sum=0;
    void traverse(TreeNode* root){
        if(root == nullptr) return;
        if(root->left) traverse(root->left);
        sum += root->val;
        if(root->right) traverse(root->right);
    }
    void convert(TreeNode* root){
        if(root == nullptr) return;
        if(root->left) convert(root->left);
        sum -= root->val;
        root->val = sum + root->val;
        if(root->right) convert(root->right);
    }
    TreeNode* convertBST(TreeNode* root) {
        traverse(root);
        cout<<sum<<endl;
        convert(root);
        return root;
    }
};

右中左

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int sum=0;
    bool isFirst=true;
    TreeNode* convertBST(TreeNode* root) {
        if(root == nullptr) return root;
        if(root->right) convertBST(root->right);
        if(isFirst){
            sum = root->val;
            isFirst=false;
        }else{
            
            sum += root->val;
            root->val = sum;  
            
        }    
        if(root->left) convertBST(root->left);
        return root;
    }

};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值