[代码随想录]二叉树篇

news2024/11/20 0:44:38

文章目录

  • 1. 二叉树之层序遍历
    • 1.1 144-二叉树的前序遍历
    • 1.2 94-二叉树的中序遍历
    • 1.3 145-二叉树的后序遍历
    • 1.4 102-二叉树的层序遍历
    • 1.5 107-二叉树的层序遍历II
    • 1.6 199-二叉树的右视图
    • 1.7* 637-二叉树的层平均值
    • 1.8* 429-N叉树的层序遍历
    • 1.9 515-在每个树行中找最大值
    • 1.10* 116-填充每个节点的下一个右侧节点指针
    • 1.11 117-填充每个节点的下一个右侧节点指针II
    • 1.12 104-二叉树的最大深度
    • 1.13 111-二叉树的最小深度
  • 2. 二叉树之常见算法
    • 2.1 226-翻转二叉树
    • 2.2 101-对称二叉树
    • 2.3* 222-完全二叉树的节点个数
    • 2.4 110-平衡二叉树
    • 2.5 257-二叉树的所有路径
    • 2.6 404-左子叶之和
    • 2.7* 513-找树左下角的值
    • 2.8 112-路径总和
    • 2.9* 106-从中序与后续遍历序列构造二叉树
    • 2.10* 105-从前序与中序遍历序列构造二叉树
    • 2.11* 654-最大二叉树
    • 2.12 617-合并二叉树
    • 2.13* 236-二叉树的最近公共祖先
  • 3. 二叉搜索树
    • 3.1 700-二叉搜索树中的搜索
    • 3.2* 98-验证二叉搜索树
    • 3.3 530-二叉搜索树的最小绝对差
    • 3.4 501-二叉搜索树中的众数
    • 3.5* 235-二叉搜索树的最近公共祖先
    • 3.6* 701-二叉搜索树中的插入操作
    • 3.7* 450-删除二叉搜索树中的节点
    • 3.8* 669-修剪二叉搜索树
    • 3.9 108-将有序数组转换为二叉搜索树
    • 3.10 538-把二叉搜索树转换为累加树

1. 二叉树之层序遍历

1.1 144-二叉树的前序遍历

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 Recursion(TreeNode* root,vector<int>& ans)
    {
        if(root == nullptr)
            return;
        ans.push_back(root->val);
        Recursion(root->left,ans);
        Recursion(root->right,ans);
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ans;
        Recursion(root,ans);
        return ans;
    }
};

迭代难度更大

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ans;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while(cur || !st.empty())
        {
            while(cur) //第一趟把左列节点放入栈和ans
            {
                ans.push_back(cur->val);
                st.push(cur);
                cur = cur->left;
            }
            TreeNode* tmp = st.top(); //对应着左下角的节点
            st.pop();
            cur = tmp->right; //开始右
        }
        return ans;
    }
};

1.2 94-二叉树的中序遍历

94
在这里插入图片描述

class Solution {
public:
    void Recursion(TreeNode* root,vector<int>& ans)
    {
        if(root == nullptr)
            return;
        Recursion(root->left,ans);
        ans.push_back(root->val);
        Recursion(root->right,ans);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ans;
        Recursion(root,ans);
        return ans;
    }
};

迭代法

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> ans;
        TreeNode* cur = root;
        while(cur || !st.empty())
        {
            while(cur)
            {
                //ans.push_back(cur->val); 并不是最左边的数据放在第一个
                st.push(cur);
                cur = cur->left;
            }
            TreeNode* tmp = st.top();
            ans.push_back(tmp->val); 
            st.pop();
            cur = tmp->right;
        }
    }
};

1.3 145-二叉树的后序遍历

145

在这里插入图片描述

class Solution 
{
public:
    void Recursion(TreeNode*& root,vector<int>& ans)
    {
        if(root==nullptr)
            return;
        Recursion(root->left,ans);
        Recursion(root->right,ans);
        ans.push_back(root->val);
    }
    vector<int> postorderTraversal(TreeNode* root) 
    {
        vector<int> ans;
        Recursion(root,ans);
        return ans;
    }
};

迭代法

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> ans;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        TreeNode* prev = nullptr;
        while(cur || !st.empty())
        {
            while(cur)
            {
                st.push(cur);
                cur=cur->left;
            }
            TreeNode* top = s.top();
            if(!top->right || top->right == prev)
            {
                ans.push_back(top->val);
                prev = top;
                st.pop();
            }
            else
                cur = top->right; //当左走完之后这一步可以走到右
        }
        return ans;
    }
};

1.4 102-二叉树的层序遍历

102

在这里插入图片描述

class Solution {
public:
    void Recursion(vector<vector<int>>& ans,TreeNode* root,int level)
    {
        if(!root)
            return;
        if(ans.size() <= level) //ans的层数不够,加层数
            ans.push_back(vector<int>());
        ans[level].push_back(root->val);
        Recursion(ans,root->left,level+1);
        Recursion(ans,root->right,level+1);
    }
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> ans;
        Recursion(ans,root,0);
        return ans;
    }
};

1.5 107-二叉树的层序遍历II

107

在这里插入图片描述

上一题reverse一下就可以了

class Solution {
public:
    void Recursion(vector<vector<int>>& ans,TreeNode* root,int level)
    {
        if(!root)
            return;
        if(ans.size() <= level)
            ans.push_back(vector<int>());
        ans[level].push_back(root->val);
        Recursion(ans,root->left,level+1);
        Recursion(ans,root->right,level+1);
    }
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        vector<vector<int>> ans;
        Recursion(ans,root,0);
        reverse(ans.begin(),ans.end());
        return ans;
    }
};

也引入一下这题(上一题)的非递归写法

class Solution {
public:
    vector<vector<int>> levelOrderBottom(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;
            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); //push进去当前层的下一层节点
                if (node->right) 
                    que.push(node->right); //同理
            }
            result.push_back(vec); //加入一层
        }
        reverse(result.begin(), result.end()); // 在这里反转一下数组即可
        return result;

    }
};

1.6 199-二叉树的右视图

199
在这里插入图片描述

class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        queue<TreeNode*> que;
        vector<int> ans;
        if(root) //加入第一个节点
            que.push(root);
        while(!que.empty())
        {
            int size = que.size();
            for(int i = 0; i < size;i++)
            {
                TreeNode* tmp = que.front();
                que.pop();
                if(i == (size-1)) //如果是位于尾部
                    ans.push_back(tmp->val);
                if(tmp->left)
                    que.push(tmp->left);//加入下一层数据
                if(tmp->right)
                    que.push(tmp->right);
            }
        }
        return ans;
    }
};

1.7* 637-二叉树的层平均值

637

在这里插入图片描述

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        queue<TreeNode*> que;
        vector<double> ans;
        if(root)
            que.push(root);
        while(!que.empty())
        {
            int size = que.size();
            double sum = 0;
            for(int i = 0; i < size; ++i)
            {
                TreeNode* tmp = que.front();
                que.pop();
                sum+=tmp->val;

                if(tmp->left)
                    que.push(tmp->left);
                if(tmp->right)
                    que.push(tmp->right);
            }
            ans.push_back(sum/size);
        }
        return ans;
    }
};

1.8* 429-N叉树的层序遍历

429

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

/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        queue<Node*> que;
        vector<vector<int>> ans;
        if(root)
            que.push(root);
        while(!que.empty())
        {
            int size = que.size();
            vector<int> tmp_v;
            for(int i = 0; i < size; ++i)
            {
                Node* node = que.front();
                que.pop();
                tmp_v.push_back(node->val);

                for(int j = 0; j < node->children.size(); ++j) //下一层节点加入que
                    if(node->children[j])
                        que.push(node->children[j]);
            }
            ans.push_back(tmp_v);
        }
        return ans;
    }
};

1.9 515-在每个树行中找最大值

515

在这里插入图片描述

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

1.10* 116-填充每个节点的下一个右侧节点指针

116

在这里插入图片描述

在这里插入图片描述

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;
    Node* next;

    Node() : val(0), left(NULL), right(NULL), next(NULL) {}

    Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}

    Node(int _val, Node* _left, Node* _right, Node* _next)
        : val(_val), left(_left), right(_right), next(_next) {}
};
*/

class Solution {
public:
    Node* connect(Node* root) {
        if(!root)
            return nullptr;
        Node* leftest = root;
        while(leftest->left) //如果该节点还有子节点,则说明可以进入循环处理其孩子
        {
            Node* cur = leftest;
            while(cur) //处理cur所有的子节点连接 
            {
                cur->left->next = cur->right; //下一层的next连接
                if(cur->next)
                    cur->right->next = cur->next->left; //下一层隔支连接
                cur = cur->next;
            }
            leftest = leftest->left; //下一层最左边开始
        }
        return root;
    }
};

若使用普通的层序遍历那么空间复杂度会达到N
而这种方式空间复杂度为1


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

117

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

上一题是完全二叉树

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;
    Node* next;

    Node() : val(0), left(NULL), right(NULL), next(NULL) {}

    Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}

    Node(int _val, Node* _left, Node* _right, Node* _next)
        : val(_val), left(_left), right(_right), next(_next) {}
};
*/

class Solution {
public:
    Node* connect(Node* root) {
        if(root && (root->left || root->right)) //root存在并且必须有一个孩子
        {
            if(root->left && root->right) //如果有左有右,则连接孩子
                root->left->next = root->right;

            //准备让孩子隔支连接
            Node* child = root->right ? root->right : root->left;
            Node* brodady = root->next; //向右移动以便用孩子连接child
            while(brodady && !(brodady->left||brodady->right)) //直到brodady走到尽头,也要找到有孩子的brodady
                brodady = brodady->next;

            child->next = brodady ? (brodady->left ? brodady->left : brodady->right) : nullptr;
            connect(root->right); //先向右初始化出NULL
            connect(root->left);
        }
        return root;
    }
};

1.12 104-二叉树的最大深度

104

在这里插入图片描述

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if(!root)
            return 0;
        return max(maxDepth(root->left), maxDepth(root->right)) + 1;
    }
};

1.13 111-二叉树的最小深度

111
在这里插入图片描述

class Solution {
public:
    int minDepth(TreeNode* root) {
        if(!root)
            return 0;
        if(!root->left && !root->right)
            return 1;
        
        int min_depth = INT_MAX;
        if(root->left)
            min_depth = min(minDepth(root->left),min_depth);
        if(root->right)
            min_depth = min(minDepth(root->right),min_depth);
        return min_depth+1;
    }
};

2. 二叉树之常见算法

2.1 226-翻转二叉树

226
在这里插入图片描述

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(!root)
            return nullptr;
        swap(root->left,root->right);
        invertTree(root->left);
        invertTree(root->right);
        return root;
    }
};

2.2 101-对称二叉树

101

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

递归

class Solution {
public:
    bool Recursion(TreeNode* left,TreeNode* right)
    {
        if(!left&&right || left&&!right) //如果长短不一
            return false;
        if(!left && !right) //如果都没有后续了
            return true;
        if(left->val != right->val)
            return false;
        return Recursion(left->left,right->right) &&
                Recursion(left->right,right->left); 
                //对称的两个节点比较
    }
    bool isSymmetric(TreeNode* root) {
        return Recursion(root->left,root->right);
    }
};

迭代(栈)

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        stack<TreeNode*> st;
        st.push(root->left);
        st.push(root->right);
        while (!st.empty()) 
        {
            TreeNode* leftNode = st.top(); 
            st.pop();
            TreeNode* rightNode = st.top(); 
            st.pop();
            if (!leftNode && !rightNode) //左右节点都不存在,相当于对称,循环至下一次判断
                continue;
            
            //左右不一样长 || 左右节点的值不一样
            if ((!leftNode || !rightNode || (leftNode->val != rightNode->val))) 
                return false;
            
            st.push(leftNode->left);
            st.push(rightNode->right);
            st.push(leftNode->right);
            st.push(rightNode->left);
        }
        return true;
    }
};

2.3* 222-完全二叉树的节点个数

222

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

递归遍历 O(N)

class Solution {
public:
    void Recursion(TreeNode* root,int& count)
    {
        if(!root)
            return;
        count++;
        Recursion(root->left,count);
        Recursion(root->right,count);
    }
    int countNodes(TreeNode* root) {
        int count = 0;
        Recursion(root,count);
        return count;
    }
};

精简版递归

class Solution {
public:
    int countNodes(TreeNode* root) {
        if (root == NULL) 
            return 0;
        return 1 + countNodes(root->left) 
                + countNodes(root->right);
    }
};

最优

class Solution {
public:
    int countNodes(TreeNode* root) 
    {
        if (!root)
            return 0;
        int level = 0;
        TreeNode* cur = root;
        while (cur->left) 
        {
            level++;
            cur = cur->left;
        }
        int low = 1 << level; // 层序遍历第low位为最深层最左侧节点序号 4
        int high = (1 << (level + 1)) - 1; //层序遍历第high位为最深层最右侧节点序号 7
        while (low < high) 
        {
            int mid = (high - low + 1) / 2 + low; //+1防止low+0 ,mid为两节点中间部分一个节点,偏右
            if (exists(root, level, mid))
                low = mid;
            else
                high = mid - 1;
        }
        return low;
    }

    bool exists(TreeNode* root, int level, int mid) //6
    {
        int bits = 1 << (level - 1); //上一层的第一位序列
        TreeNode* cur = root;
        while (cur && bits > 0) 
        {
            if (bits & mid)  //0010 0110 0010 当不再同一树时判断后就进入循环
                cur = cur->right;
            else
                cur = cur->left;
            bits >>= 1; //bits是最左节点,往上靠
        }
        return cur != nullptr;
    }
};

时间复杂度:O(logN*logN)
空间复杂度:O(1)


2.4 110-平衡二叉树

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

class Solution {
public:
    int Recursion(TreeNode* root)
    {
        if(!root)
            return 0;
        int left = Recursion(root->left);
        if(left == -1)
            return -1;
        int right = Recursion(root->right);
        if(right == -1)
            return -1;
        if(abs(left-right) > 1)
            return -1; //执行后,以后的结果都为-1,递归其实已经可以看作结束了
        return left>right?left+1:right+1; //每一层都会记录层数+1
    }
    bool isBalanced(TreeNode* root) 
    {
        if(Recursion(root) == -1)
            return false;
        return true;   
    }
};

2.5 257-二叉树的所有路径

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

class Solution {
public:
    void Recursion(TreeNode* root,vector<string>& vs,string s) //s传的是临时拷贝份
    {
        if(root&&!root->left&&!root->right) //无子,此时不加->
        {
            s+=(to_string(root->val));
            vs.push_back(s);
            return;
        }
        if(!root)
            return;
        s+=(to_string(root->val)+"->");
        Recursion(root->left,vs,s); 
        Recursion(root->right,vs,s); 
    }
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> vs;
        string s;
        Recursion(root,vs,s);
        return vs;
    }
};

2.6 404-左子叶之和

404
在这里插入图片描述

class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        if (!root) 
            return 0;
        int leftValue = 0;
        if (root->left && !root->left->left && !root->left->right) //左子存在且为叶
            leftValue = root->left->val;
        
        return leftValue + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
    }
};

2.7* 513-找树左下角的值

513

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

dfs

class Solution {
public:
    void Recursion(TreeNode* cur,int curdep,int& maxdep,int& ans)
    {
        if(!cur->left&&!cur->right)
        {
            if(curdep>maxdep)
            {
                maxdep = dep;
                ans = cur->val;
            }
            return;
        }
        if(cur->left) //cur->left在前面使得更早的占用ans,以防被right占用
            Recursion(cur->left,dep+1,maxdep,ans);
        if(cur->right)
            Recursion(cur->right,dep+1,maxdep,ans);
    }
    int findBottomLeftValue(TreeNode* root) {
        int ans = root->val;
        int maxdep = 0;
        Recursion(root,0,maxdep,ans);
        return ans;
    }
};

bfs

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        int ans = 0;
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty())
        {
            TreeNode* cur = que.front();
            que.pop();
            if(cur->right)
                que.push(cur->right);
            if(cur->left)
                que.push(cur->left);
            ans = cur->val;
        }
        return ans;
    }
};

2.8 112-路径总和

112

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

class Solution {
public:
    bool Recursion(TreeNode* cur,int sum,int target)
    {
        if(!cur)
            return false;
        if(!cur->left&&!cur->right&&sum+cur->val == target)
            return true;
        
        return Recursion(cur->left,sum+cur->val,target)
            ||Recursion(cur->right,sum+cur->val,target);
    }
    bool hasPathSum(TreeNode* root, int targetSum) {
        return Recursion(root,0,targetSum);
    }
};

2.9* 106-从中序与后续遍历序列构造二叉树

106

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

class Solution {
public:
    TreeNode* Recursion(vector<int>& inorder,vector<int>& postorder,int& rootindex,int left,int right)
    {
        if(left > right)
            return nullptr;
        TreeNode* cur = new TreeNode(postorder[rootindex]); //cur为当前根节点
        int mid = 0;
        for(mid = inorder.size()-1 ; mid >=0 ; --mid)
            if(inorder[mid] == postorder[rootindex])
                break;
        //此时mid为inorder的根坐标
        rootindex--; //跳到下一个根
        //因为是后序所以先right,否则会出现构建出相反的树,并且大概率导致rootindex<0而导致的越栈
        cur->right = Recursion(inorder,postorder,rootindex,mid+1,right);
        cur->left = Recursion(inorder,postorder,rootindex,left,mid-1);
        return cur;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        int rootindex = postorder.size() - 1;
        return Recursion(inorder,postorder,rootindex,0,rootindex);
    }
};

2.10* 105-从前序与中序遍历序列构造二叉树

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

class Solution {
public:
    TreeNode* Recursion(vector<int>& preorder, vector<int>& inorder,int& rootindex,int left , int right)
    {
        if(left > right)
            return nullptr;
        TreeNode* cur = new TreeNode(preorder[rootindex]);
        int mid = 0;
        for(mid = 0 ; mid < inorder.size() ; ++mid)
            if(inorder[mid] == preorder[rootindex])
                break;
        rootindex++;
        cur->left = Recursion(preorder,inorder,rootindex,left,mid-1);
        cur->right = Recursion(preorder,inorder,rootindex,mid+1,right);
        return cur;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int rootindex = 0;
        return Recursion(preorder,inorder,rootindex,0,preorder.size()-1);
    }
};

2.11* 654-最大二叉树

654

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

class Solution {
public:
    TreeNode* Recursion(vector<int>& nums,int left,int right)
    {
        if(left > right)
            return nullptr;
        int mid = left; //坐标
        int max = 0;    //最大值
        for(int i = mid ; i <= right ; ++i)
        {
            if(nums[i] > max)
            {
                mid = i;       //mid就是根的坐标
                max = nums[i]; //最大值就是根
            }
        }
        TreeNode* cur = new TreeNode(max); //构建根
        cur->left = Recursion(nums,left,mid-1);
        cur->right = Recursion(nums,mid+1,right);
        return cur;
    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return Recursion(nums,0,nums.size()-1);
    }
};

2.12 617-合并二叉树

617

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

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        if(!root1)
            return root2; //如果两个节点都不存在,也会返回nullptr(root2)
        if(!root2)
            return root1;
        TreeNode* root = new TreeNode(root1->val+root2->val);
        root->left = mergeTrees(root1->left,root2->left);
        root->right = mergeTrees(root1->right,root2->right);
        return root;
    }
};

2.13* 236-二叉树的最近公共祖先

236

在这里插入图片描述

在这里插入图片描述

/**
 * 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) {
        if(!root)
            return nullptr;
        if(root == p || root == q)
            return root;
            
        TreeNode* left = lowestCommonAncestor(root->left,p,q);
        TreeNode* right = lowestCommonAncestor(root->right,p,q);

        if(left&&right)
            return root;
        else if(!left&&right)
            return right;
        else if(left&&!right)
            return left;
        else
            return nullptr;
    }
};

3. 二叉搜索树

3.1 700-二叉搜索树中的搜索

700

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

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

3.2* 98-验证二叉搜索树

98

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

class Solution {
public:
    bool isValidBST(TreeNode* root,TreeNode* minNode = nullptr,TreeNode* maxNode = nullptr) {
        if(!root)
            return true;
        if((minNode && root->val <= minNode->val) || //右树用来判断是否比父小
            (maxNode && root->val >= maxNode->val))  //左树用来判断是否比父大
            return false;                            //不符合就false
            
        return isValidBST(root->left,minNode,root) && //对于左树,最大的就是根
                isValidBST(root->right,root,maxNode); //对于右树,最小的就是根
    }
};

更直观的方法

class Solution {
public:
    bool isValidBST(TreeNode* root) 
    {
        if(!root)
            return true;
        if(root->left)
        {
            TreeNode* tmp = root->left;
            if(tmp->val>=root->val) //先判断和父的关系是否满足
                return false;
            while(tmp->right)       //在判断自己的右孩子是否和自己对应
            {                       //左孩子会通过递归(和父的关系)进行判断
                tmp = tmp->right;
                if(tmp->val>=root->val)
                    return false;
            }
        }
        if(root->right)
        {
            TreeNode* tmp = root->right;
            if(tmp->val<=root->val)
                return false;
            while(tmp->left)
            {
                tmp = tmp->left;
                if(tmp->val<=root->val)
                    return false;
            }
        }
        return isValidBST(root->left) && isValidBST(root->right);
    }
};

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

530

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

递归

class Solution {
public:
    void Recursion(TreeNode* root,TreeNode*& prev,int& mindif)
    {
        if(!root)
            return;
        Recursion(root->left,prev,mindif);
        if(prev)
            mindif = min(mindif,abs(root->val-prev->val));
            
        prev = root; //prev就是更深层的
        Recursion(root->right,prev,mindif);
    }
    int getMinimumDifference(TreeNode* root) 
    {
        int mindif = INT_MAX;
        TreeNode* prev = nullptr;
        Recursion(root,prev,mindif); //类似于采取中序遍历寻找mindif
        return mindif;
    }
};

完全遍历

class Solution {
public:
    void Recursion(TreeNode* root,int& min)
    {
        if(!root)
            return;
        int tmp;
        if(root->left)
        {
            TreeNode* left = root->left;
            while(left)
            {
                tmp =abs(root->val-left->val);
                if(tmp<min)
                    min = tmp;
                left = left->right;
            }
        }
        if(root->right)
        {
            TreeNode* right = root->right;
            while(right)
            {
                tmp = abs(root->val-right->val);
                if(tmp<min)
                    min = tmp;
                right = right->left;
            }
        }
        Recursion(root->left,min);
        Recursion(root->right,min);
    }
    int getMinimumDifference(TreeNode* root) 
    {
        int min = 100000;
        Recursion(root,min);
        return min;
    }
};

3.4 501-二叉搜索树中的众数

501

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

hash通解,即非二叉树也可解

class Solution {
public:
    void Init_um_Recursion(TreeNode* root,unordered_map<int,int>& um)
    {
        if(!root)
            return;
        um[root->val]++;
        Init_um_Recursion(root->left,um);
        Init_um_Recursion(root->right,um);
    }
    vector<int> findMode(TreeNode* root) {
        unordered_map<int,int> um;
        Init_um_Recursion(root,um);

        vector<int> ans;
        int max = INT_MIN;
        for(auto& e : um) //算出最多的出现次数
            if(e.second > max)
                max = e.second;

        for(auto& e : um)
            if(e.second == max)
                ans.push_back(e.first);
        
        return ans;
    }
};

针对

/**
 * 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 samenum = 0;
    int count = 0;
    int maxcount = 0;
    void Get_ret(TreeNode* root,vector<int>& ret)
    {
        if(!root)
            return;
        Get_ret(root->left,ret);
        ret.push_back(root->val);

        if(samenum == root->val) //即使samenum初始值就和val相同也无所谓
            count++;
        else
        {
            samenum = root->val;
            count=1; //避免samenum初始就和val相同而导致的错误计数,也方便使用
        }

        if(maxcount < count)
            maxcount = count;
        Get_ret(root->right,ret);
    }
    
    vector<int> findMode(TreeNode* root) {
        vector<int> ans;
        vector<int> ret;
        Get_ret(root,ret);

        int left = 0;
        int right = maxcount-1; //left到right 可看作是窗口
        while(right < ret.size())
        {
            if(ret[left] == ret[right])
            {
                ans.push_back(ret[left]);
                left = right+1;
                right = left+maxcount-1;
            }
            else
            {
                left++;
                right++;
            }
        }
        return ans;
    }
};

3.5* 235-二叉搜索树的最近公共祖先

235

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

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 
    {
        if(!root)
            return nullptr;
        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);
        return root;
    }
};

3.6* 701-二叉搜索树中的插入操作

701

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

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

3.7* 450-删除二叉搜索树中的节点

450

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

class Solution {
public:
    TreeNode* findMin(TreeNode* node) 
    {
        while (node->left) 
            node = node->left;
        return node;
    }

    TreeNode* deleteNode(TreeNode* root, int key) {
        if (!root) 
            return root;

        if (key < root->val) 
            root->left = deleteNode(root->left, key);
        else if (key > root->val) 
            root->right = deleteNode(root->right, key);
        else 
        {
            if (!root->left) 
            {
                TreeNode* temp = root->right;
                delete root;
                return temp;
            }
            else if (!root->right) 
            {
                TreeNode* temp = root->left;
                delete root;
                return temp;
            }

            TreeNode* temp = findMin(root->right); //temp就是要替代的节点
            root->val = temp->val;
            root->right = deleteNode(root->right, temp->val);
        }
        return root;
    }
};

3.8* 669-修剪二叉搜索树

669

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

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) 
    {
        if(!root)
            return nullptr; //间接删除
        if(root->val<low) //范围全在右子树上
            return trimBST(root->right,low,high);
        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;
    }
};

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

108

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

class Solution {
public:
    TreeNode* Recursion(vector<int>& nums,int left,int right)
    {
        if(left>right)
            return nullptr;
        int mid = left+((right-left)>>1); // >>1 可看作是 /2,默认左偏
        TreeNode* newnode = new TreeNode(nums[mid]);
        newnode->left = Recursion(nums,left,mid-1);
        newnode->right = Recursion(nums,mid+1,right);
        return newnode;
    }

    TreeNode* sortedArrayToBST(vector<int>& nums) 
    {
        return Recursion(nums,0,nums.size()-1);
    }
};

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

538

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

class Solution {
public:
    void Recursion(TreeNode* root,int& val)
    {
        if(!root)
            return;
        Recursion(root->right,val);
        val+=root->val;
        root->val = val;
        Recursion(root->left,val);
    }
    TreeNode* convertBST(TreeNode* root) {
        int val = 0;
        Recursion(root,val);
        return root;
    }
};

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

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

相关文章

【算法挨揍日记】day14——724. 寻找数组的中心下标、238. 除自身以外数组的乘积

724. 寻找数组的中心下标 724. 寻找数组的中心下标 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;请计算数组的 中心下标 。 数组 中心下标 是数组的一个下标&#xff0c;其左侧所有元素相加的和等于右侧所有元素相加的和。 如果中心下标位于数组最左端&#…

客户成功体系如何构建?请看这7步

⭐简单说两句⭐ 作者&#xff1a;后端小知识 CSDN个人主页&#xff1a;后端小知识 &#x1f50e;GZH&#xff1a;后端小知识 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; 客户成功体系如何构建&#xff1f;请看这7步 在中国企业服务领域的…

js获取当前月第一天最后一天

【版权所有&#xff0c;文章允许转载&#xff0c;但须以链接方式注明源地址&#xff0c;否则追究法律责任】【创作不易&#xff0c;点个赞就是对我最大的支持】 前言 仅作为学习笔记&#xff0c;供大家参考 总结的不错的话&#xff0c;记得点赞收藏关注哦&#xff01; 目录 …

C++ DAY 5

#include <iostream>using namespace std;class Sofa { private:string sit; public:Sofa(string s "-") :sit(s){cout << "sofa 构造函数" << endl;}void show (){cout << sit << endl;} }; class Bed { private:string sl…

Spring框架是什么Spring框架的体系结构

Spring框架是什么 Spring是为企业Java最流行的应用程序开发框架。数以百万计的世界各地的开发人员使用Spring框架来创建高性能&#xff0c;易于测试的&#xff0c;可重用的代码。 Spring框架是一个开源的Java平台&#xff0c;它最初是由Rod Johnson编写并在2003年6月在Apache2…

Logo设计教程:从入门到精通的全程指导

如果你想制作一个专业的Logo标识&#xff0c;但是又缺乏设计技能&#xff0c;那么乔拓云可以帮助你轻松完成这个任务。以下是通过乔拓云制作Logo标识的简单步骤&#xff1a; 1. 注册并登录乔拓云账号 访问乔拓云官网&#xff0c;注册并登录你的账号。登录后&#xff0c;你将进…

麒麟系统加密/麒麟系统防泄密

​深信达网络科技有限公司自主研发的深信达主机加固系统软件V2.0、深信达沙盒防泄密系统软件V5.0&#xff0c;与麒麟软件完成兼容认证&#xff0c;并被纳入麒麟软件安全生态联盟成员之一。 麒麟软件主要面向通用和专用领域打造安全创新操作系统产品和相应解决方案&#xff0c;以…

Linux 中如何安全地抹去磁盘数据?

哈喽大家好&#xff0c;我是咸鱼 离过职的小伙伴都知道&#xff0c;离职的时候需要上交公司电脑&#xff0c;但是电脑里面有许多我们的个人信息&#xff08;聊天记录、浏览记录等等&#xff09; 所以我们就需要先把这些信息都删除&#xff0c;确保无法恢复之后才上交 即有些…

Etsy店铺爆单的7个技巧

2023年跨境电商行业趋势愈发旺盛&#xff0c;目前正处于红利期&#xff0c;而作为近年来的电商网红“Etsy”&#xff0c;以其低成本低竞争高回报的优势吸引了大批的跨境电商玩家。但仅仅入驻照搬其他平台经验很难出单&#xff0c;如果你正烦恼这个问题&#xff0c;那么接下来的…

人工智能在教育上的应用2-基于大模型的未来数学教育的情况与实际应用

大家好&#xff0c;我是微学AI ,今天给大家介绍一下人工智能在教育上的应用2-基于大模型的未来数学教育的情况与实际应用&#xff0c;随着人工智能(AI)和深度学习技术的发展&#xff0c;大模型已经开始渗透到各个领域&#xff0c;包括数学教育。本文将详细介绍基于大模型在数学…

User Account Status 在CDB 和PDB不一致的情况 OPEN IN ROLLOVER

PDB&#xff1a; OPEN & IN ROLLOVER CDB&#xff1a; OPEN 解决办法 alter user C## expire password rollover period; select pdb.NAME, pdb.CREATION_TIME pdbcreated,du.username,du.account_status,du.LOCK_DATE,du.EXPIRY_DATE,du.CREATED,du.LAST_LOGIN,du.pro…

第十二章-系统调用

Ⅰ.Linux系统调用原理 Linux系统调用都通过中断号int 0x80完成&#xff0c;不同的系统调用函数对应eax中不同的子功能号&#xff0c;因此系统调用包括int 0x80; mov %sub_num,%%eax两个部分。 Linux系统调用包括两种方式&#xff1a;1.宏调用_syscall。2.库函数调用syscall。…

拼多多怎么引流商家?建议收藏的几个方法,拼多多引流脚本详细使用教学分享

大家好我是你们的小编一辞脚本&#xff0c;今天给大家分享新的知识&#xff0c;很开心可以在CSDN平台分享知识给大家,很多伙伴看不到代码我先录制一下视频 在给大家做代码&#xff0c;几个关于商家引流的知识今天给大家分享一下拼多多引流脚本的知识和视频演示 不懂的小伙伴可…

【微服务治理】Spring Cloud 断路器Hystrix实战应用

系列文章目录 第一章 Java线程池技术应用 第二章 CountDownLatch和Semaphone的应用 第三章 Spring Cloud 简介 第四章 Spring Cloud Netflix 之 Eureka 第五章 Spring Cloud Netflix 之 Ribbon 第六章 Spring Cloud 之 OpenFeign 第七章 Spring Cloud 之 GateWay 第八章 Sprin…

es elasticsearch 基础

es https://www.elastic.co/guide/en/elasticsearch/reference/6.8/getting-started.html 倒排索引&#xff1a; 正排–>从目录到文章内容 倒排–>内容到目录文章标题 if we dont need full text search ,we dont need to create 倒排 using text type 分词&#xff1a…

优雅而高效的JavaScript——解构赋值

&#x1f643;博主&#xff1a;小猫娃来啦 &#x1f643;文章核心&#xff1a;优雅而高效的JavaScript——解构赋值 文章目录 什么是解构赋值数组解构赋值基本用法默认值剩余参数 对象解构赋值基本用法默认值剩余参数 解构赋值的优势和应用场景代码简化和可读性提高交换变量值函…

硬件基本功--过流、过压保护电路

1.简介 过流保护(OCP)&#xff1a;当电路电流超过预定最大值时&#xff0c;使保护装置动作的一种保护方式。不允许超过预定最大值电流&#xff0c;不然会烧坏电路的器件。过压保护(OVP)&#xff1a;被保护电路电压超过预定的最大值时&#xff0c;使电源断开或使受控设备电压降低…

企业如何实现财务无纸化?票档一体化建设势在必行

随着“大智移云物区”等信息技术的发展&#xff0c;传统的财务管理开始向信息化、数字化转型&#xff0c;电子发票、电子凭证也逐渐取代传统的纸质档案资料&#xff0c;促使企业转型升级并逐步实现财务无纸化&#xff0c;助力降本增效。 同时&#xff0c;在政策强力推动下&…

【赠书活动】如何提高C++代码的性能

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

C++QT-day5

#include <iostream> //多继承using namespace std;class Sofa { private:string sitting; public:Sofa(){cout << "Sofa无参构造函数" << endl;}Sofa(string sitting):sitting(sitting){cout << "Sofa有参构造函数" << …