代码随想录二叉树专题


今天刷完了二叉树专题,

二叉树

二叉树的理论基础

在这里插入图片描述

1.满二叉树

满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。

2.完全二叉树

完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2^(h-1) 个节点。
在这里插入图片描述

3.二叉搜索树

前面介绍的树,都没有数值的,而二叉搜索树是有数值的了,二叉搜索树是一个有序树。
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
它的左、右子树也分别为二叉排序树

4.二叉树的递归遍历

 //前序遍历:根左右
class Solution {
public:
    void traversal(TreeNode *cur,vector<int>&res){
        if(cur==nullptr) return;
        res.push_back(cur->val);
        traversal(cur->left,res);
        traversal(cur->right,res);
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int>result;
        traversal(root,result);
        return result;
    }
};

//中序遍历:左右根
class Solution {
public:
    void Inorder(TreeNode *cur,vector<int>&res){
        if(cur==nullptr) return ;
        Inorder(cur->left,res);
        res.push_back(cur->val);
        Inorder(cur->right,res);
    }
    vector<int> inorderTraversal(TreeNode* root) {
    vector<int>ans;
    Inorder(root,ans);
    return ans;
    }
};

//后序遍历:左右根
class Solution {
public :     
    void  Order(TreeNode *cur,vector<int>&res){
        if(cur==nullptr) return;
        Order(cur->left,res);
        Order(cur->right,res);
        
        res.push_back(cur->val);
    }
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int>ans;
        Order(root,ans);
        return ans;
    }
};

5.二叉树的迭代遍历(基础必须掌握)

//二叉树的前序遍历:根左右
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
//只掌握递归写法完全不够,还需掌握迭代写法(很基础)
//利用栈实现树的前序遍历
    vector<int>res;
    if(root==nullptr){
        return res;
    }
    stack<TreeNode *>st;
    st.push(root);
    while(!st.empty()){
        TreeNode *node =st.top();
        st.pop();
        res.push_back(node->val);
        if(node->right) st.push(node->right); //因为是栈,所以是先进栈右节点
        if(node->left)  st.push(node->left);  //

    }
    return res;
    }
};
//二叉树的中序遍历:
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
//中序遍历:左根右
    vector<int>res;
    stack<TreeNode *>st;
    while(root!=nullptr||!st.empty()){
        while(root!=nullptr){
            st.push(root);
            root=root->left;
        }
        root=st.top();
        st.pop();
        res.push_back(root->val);
        root=root->right;

    }
    return res;
    }
};

//二叉树的后序遍历:先序遍历是中左右,后续遍历是左右中,那么我们只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序,然后在反转result数组,输出的结果顺序就是左右中了
//后序遍历:左右根
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
     vector<int>res;
     if(root==nullptr){
         return res;
     } 
     stack<TreeNode*>st;
     st.push(root);
     while(!st.empty()){
        TreeNode *node=st.top();
        st.pop();
        res.push_back(node->val);
        if(node->left) st.push(node->left);
        if(node->right) st.push(node->right);
     } 
     reverse(res.begin(),res.end());
     return res;
        
    }
};

二叉树的统一迭代法

6.二叉数的层序遍历

BFS 的使用场景总结:层序遍历、最短路径问题
可以参考这篇点赞2k+的题解:链接: link

102. 二叉树的层序遍历
//层序遍历的模板
class Solution {
public:
//使用一个队列
    vector<vector<int>> levelOrder(TreeNode* root) {
    queue<TreeNode*>que;
    if(root!=nullptr) que.push(root);
    vector<vector<int>>res;
    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();//front访问第一个元素,back访问最后一个元素
        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);     
    }
    return res;
    }
};
//递归法实现
class Solution {
public:
    void order(TreeNode* cur, vector<vector<int>>& result, int depth)
    {
        if (cur == nullptr) return;
        if (result.size() == depth) result.push_back(vector<int>());
        result[depth].push_back(cur->val);
        order(cur->left, result, depth + 1);
        order(cur->right, result, depth + 1);
    }
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> result;
        int depth = 0;
        order(root, result, depth);
        return result;
    }
}
  1. 二叉树的层序遍历 II
class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
//返回其节点值 自底向上的层序遍历:二叉树的遍历的逆序
    queue<TreeNode *>que;
    if(root!=nullptr) que.push(root);
    vector<vector<int>>res;
    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;
    }
};

199.二叉树的右视图

//bfs:O(N),o(N)
class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
//使用层序遍历,并只保留每层最后一个节点的值
    queue<TreeNode *>que;
    if(root!=nullptr) que.push(root);
    vector<int>res;
    while(!que.empty()){
        int size=que.size();
        for(int i=0;i<size;++i){
            TreeNode *node=que.front();
            que.pop();
            if(i==(size-1)) res.push_back(node->val);
            if(node->left) que.push(node->left);
            if(node->right) que.push(node->right);
        }
    }
    return res;
    }
};
//DFS:我们按照 「根结点 -> 右子树 -> 左子树」 的顺序访问,就可以保证每层都是最先访问最右边的节点的。(与先序遍历 「根结点 -> 左子树 -> 右子树」 正好相反,先序遍历每层最先访问的是最左边的节点)
class Solution {
public:
    
    void dfs(TreeNode *root,vector<int>&res,int depth){
        if(root==nullptr){
            return ;
        }
    //先访问当前节点,再递归的访问右子树和左子树
        if(depth==res.size()){
/*如果当前节点所在的深度还没有出现再res里,
说明在该深度下当前节点是第一个被访问的节点,因此将当前节点加入res中
*/
            res.push_back(root->val);
        }
        
        dfs(root->right,res,depth+1);
        dfs(root->left,res,depth+1);
    }
    vector<int> rightSideView(TreeNode* root) {
        vector<int>res;
        dfs(root,res,0);
        return res;

    }
};

7.反转二叉树

//递归法
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(root==nullptr) return nullptr;
        TreeNode *rightTree=root->right;
        root->right=invertTree(root->left);
        root->left=invertTree(rightTree);
        return root;
    }
};
//

N叉树的前后序遍历(n叉树没有中序遍历)

1.n叉树的前序遍历

class Solution {
public:
    void helper(Node *cur,vector<int>&res){
        if(cur==nullptr) return ;
        res.push_back(cur->val);
        for(auto ch:cur->children){
            helper(ch,res);
        }
    }
    vector<int> preorder(Node* root) {
        vector<int>res;
        
        helper(root,res);
        return res;
    }
};

2.n叉树的后序遍历

class Solution {
public:
    void helper(Node *cur,vector<int>&res){
        if(cur==nullptr) return ;
        for(auto ch:cur->children){
            helper(ch,res);
        }
        res.push_back(cur->val);
    }
    vector<int> postorder(Node* root) {
      vector<int>res;
      helper(root,res);
      return res;  
    }
};

8.对称二叉树

101.对称二叉树

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(root==nullptr)return true;
        return dfs(root->left,root->right);
    }
    bool dfs(TreeNode *left,TreeNode *right){
        if(left==nullptr&&right==nullptr){
            return true;
        }
        if(left==nullptr||right==nullptr||left->val!=right->val){
            return false;
        }
        return dfs(left->left,right->right)&&dfs(left->right,right->left);
    }
};

相似题目:
100.相同的树

class Solution {
public:
    bool isSameTree(TreeNode* p, TreeNode* q) {
//如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的
    if(p==nullptr&&q==nullptr) return true;
    if(p==nullptr||q==nullptr||p->val!=q->val) return false;
    return isSameTree(p->left,q->left)&&isSameTree(p->right,q->right);
    }
};

572.另一棵树的子树

class Solution {
public:
    bool isSubtree(TreeNode* root, TreeNode* subRoot) {
/*
首先判断一个树是否是另一棵树的子树,很明显想到可以用递归,但是两棵树完全相同也可以看做一棵树是另一棵树的子树。
所以自然而然想到用一个判断两棵树是否相同的递归函数。
*/
    if(subRoot==nullptr) return true;
    if(root==nullptr)   return false;
    return isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot)||isSameTree(root,subRoot);
    }
    bool isSameTree(TreeNode *s,TreeNode *t){
        if(s==nullptr&&t==nullptr) return true;
        if(s==nullptr||t==nullptr) return false;
        if(s->val!=t->val) return false;
        return isSameTree(s->left,t->left)&&isSameTree(s->right,t->right);
    }
};

9.二叉树的最大深度

111.二叉树的最小深度

class Solution {
public:
    int getDepth(TreeNode *cur){
        if(cur==nullptr) return 0;
        int leftDepth=getDepth(cur->left);
        int rightDepth=getDepth(cur->right);
        if(cur->left==nullptr&&cur->right!=nullptr){
            return 1+rightDepth;
        }
        if(cur->right==nullptr&&cur->left!=nullptr){
            return 1+leftDepth;
        }
        int res=1+min(leftDepth,rightDepth);
        return res;
    }
    int minDepth(TreeNode* root) {
        return getDepth(root);
    }
};

精简一下代码:

class Solution {
public:
    int minDepth(TreeNode* root) {
    if(root==nullptr) return 0;
    int m1=minDepth(root->left);
    int m2=minDepth(root->right);
    //1.如果左孩子和右孩子有为空的情况,直接返回m1+m2+1
    //2.如果都不为空,返回较小深度+1
    return root->left==nullptr||root->right==nullptr?m1+m2+1:min(m1,m2)+1;
    }
};

10.完全二叉树的节点个数

class Solution {
public:
    int countNodes(TreeNode* root) {
//层序遍历:迭代法
    queue<TreeNode*>que;
    int count=0;
    if(root!=nullptr) que.push(root);
    while(!que.empty()){
        int size=que.size();
        for(int i=0;i<size;++i){
            TreeNode *node=que.front();
            que.pop();
            count++;
            if(node->left) que.push(node->left);
            if(node->right) que.push(node->right);
        }

    }
    return count;
    }
};
//递归法
class Solution {
public:
    int countNodes(TreeNode* root) {
    if(root==nullptr) return 0;
    return 1+countNodes(root->left)+countNodes(root->right);
    }
};

11.平衡二叉树

lass Solution {
public:
//一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1
    int getDepth(TreeNode *cur){
        if(cur==nullptr) return 0;
        int leftHeight=getDepth(cur->left);
        if(leftHeight==-1) return -1;
        int rightHeight=getDepth(cur->right);
        if(rightHeight==-1) return -1;
        return abs(leftHeight-rightHeight)>1?-1:1+max(leftHeight,rightHeight);
    }
    bool isBalanced(TreeNode* root) {
        return getDepth(root)==-1? false:true;

    }
};

13.二叉树的所有路径

class Solution {
public:
    void dfs(TreeNode *cur,string path,vector<string>&res){
        if(cur==nullptr) return;
        //to_string 函数:将数字常量转换为字符串,返回值为转换完毕的字符串
        path+=to_string(cur->val);
        if(cur->left==nullptr&&cur->right==nullptr){
            res.push_back(path);
        }else{
            path+="->";
            dfs(cur->left,path,res);
            dfs(cur->right,path,res);
        }
    }
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string>res;
        string path;
        dfs(root,path,res);
        return res;
    }
};

14.左叶子之和

class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
//首先要注意是判断左叶子,不是二叉树左侧节点
    if(root==nullptr) return 0;
    int res=0;
    if(root->left!=nullptr&&root->left->left==nullptr&&root->left->right==nullptr){
        res+=root->left->val;
    }
    return res+sumOfLeftLeaves(root->left)+sumOfLeftLeaves(root->right);
    }
};

15.找树左下角的指

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
//层序遍历:只需记录最后一行,第一个节点的数值就可以
    queue<TreeNode *>que;
    int res;
    if(root!=nullptr) que.push(root);
    while(!que.empty()){
        int size=que.size();
        for(int i=0;i<size;++i){
            TreeNode *node=que.front();
            que.pop();
            if(i==0) res=node->val;//记录最后一行的第一个节点的数值
            if(node->left) que.push(node->left);
            if(node->right) que.push(node->right);

        }
    }
    return res;
    }
};
class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
//层序遍历,从右往左添加结点,最后访问的一个结点即为最后一层最左边的。
    queue<TreeNode *>que;
    int res;
    if(root==nullptr) return 0;
    que.push(root);
    while(!que.empty()){
        auto p=que.front();
        que.pop();
        if(p->right) que.push(p->right);
        if(p->left)  que.push(p->left);
        res=p->val;
    }
    return res;
    }
};

17.路径总和

112.路径总和

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
//递归法:dfs
    if(root==nullptr) return false;//经典先判空
    if(root->left==nullptr&&root->right==nullptr){
        return root->val-targetSum==0;
    }
    return hasPathSum(root->left,targetSum-root->val)||hasPathSum(root->right,targetSum-root->val);
    }
};
class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
//广度优先遍历,记录从根节点到当前节点的路径和
    if(root==nullptr) return false;
    queue<TreeNode*>que_node;
    queue<int>que_val;
    que_node.push(root);
    que_val.push(root->val);
    while(!que_node.empty()){
        TreeNode *node=que_node.front();
        int tmp=que_val.front();
        que_node.pop();
        que_val.pop();
        if(node->left==nullptr&&node->right==nullptr){
            if(tmp==targetSum){
                return true;
            }
        }
        if(node->left!=nullptr){
            que_node.push(node->left);
            que_val.push(node->left->val+tmp);
        }
        if(node->right!=nullptr){
            que_node.push(node->right);
            que_val.push(node->right->val+tmp);
        }

    }
    return false;
    }
};

113.路径之和2

class Solution {
public:
//[[5,4,11,2],[5,8,4,5]],看到这种输出结果,肯定需要一个一维数组一个二维数组
//dfs:我们可以采用深度优先搜索的方式,枚举每一条从根节点到叶子节点的路径。
//当我们遍历到叶子节点,且此时路径和恰为目标和时,我们就找到了一条满足条件的路径。
    vector<vector<int>>res;
    vector<int>path;
    void dfs(TreeNode *root,int targetSum){
        if(root==nullptr) return;
        path.push_back(root->val);
        targetSum-=root->val;
        if(root->left==nullptr&&root->right==nullptr&&targetSum==0){
            res.push_back(path);
        }
        dfs(root->left,targetSum);
        dfs(root->right,targetSum);
        path.pop_back();
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        dfs(root,targetSum);
        return res;
    }
};
//bfs
class Solution {
public:
    vector<vector<int>> ret;
    unordered_map<TreeNode*, TreeNode*> parent;

    void getPath(TreeNode* node) {
        vector<int> tmp;
        while (node != nullptr) {
            tmp.emplace_back(node->val);
            node = parent[node];
        }
        reverse(tmp.begin(), tmp.end());
        ret.emplace_back(tmp);
    }

    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        if (root == nullptr) {
            return ret;
        }

        queue<TreeNode*> que_node;
        queue<int> que_sum;
        que_node.emplace(root);
        que_sum.emplace(0);

        while (!que_node.empty()) {
            TreeNode* node = que_node.front();
            que_node.pop();
            int rec = que_sum.front() + node->val;
            que_sum.pop();

            if (node->left == nullptr && node->right == nullptr) {
                if (rec == targetSum) {
                    getPath(node);
                }
            } else {
                if (node->left != nullptr) {
                    parent[node->left] = node;
                    que_node.emplace(node->left);
                    que_sum.emplace(rec);
                }
                if (node->right != nullptr) {
                    parent[node->right] = node;
                    que_node.emplace(node->right);
                    que_sum.emplace(rec);
                }
            }
        }

        return ret;
    }
};


1026.节点与其祖先之间的最大差值

class Solution {
public:
    int ans=0;
    void dfs(TreeNode *cur,int mx,int mn){
        if(cur==nullptr) return;
 // 虽然题目要求「不同节点」,但是相同节点的差值为 0,不会影响最大差值
// 所以先更新 mn 和 mx,再计算差值也是可以的
// 在这种情况下,一定满足 mn <= node.val <= mx

        mx=max(mx,cur->val);
        mn=min(mn,cur->val);
        ans=max(ans,max(cur->val-mn,mx-cur->val));
        dfs(cur->left,mx,mn);
        dfs(cur->right,mx,mn);
    }

    int maxAncestorDiff(TreeNode* root) {
//维护最大值,最小值即可。
    dfs(root,root->val,root->val);
    return ans;
    }
};

18.由俩个遍历序列构建二叉树

class Solution {
public:
    TreeNode *dfs(vector<int>&inorder,vector<int>&postorder){
        if(postorder.size()==0) return nullptr;
        //后序遍历数组的最后一个元素,就是当前的中间节点
        int rootValue=postorder[postorder.size()-1];
        TreeNode *root=new TreeNode(rootValue);
        if(postorder.size()==1) return root;
        //找到中序遍历的切割点·
        int index;
        for(index=0;index<inorder.size();++index){
            if(inorder[index]==rootValue) break;
        }
        //切割中序数组
        //左闭右开区间:[o,index)[index,size]
        vector<int>leftInorder(inorder.begin(),inorder.begin()+index);
        vector<int>rightInorder(inorder.begin()+index+1,inorder.end());
        postorder.resize(postorder.size()-1);
        //切割后序数组
        vector<int>leftPostorder(postorder.begin(), postorder.begin()+leftInorder.size());
        vector<int>rightPostorder(postorder.begin()+leftInorder.size(),postorder.end());
        root->left=dfs(leftInorder,leftPostorder);
        root->right=dfs(rightInorder,rightPostorder);
        return root;
        

    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
/* 从中序与后序遍历序列构造二叉树,;理论清楚,那么代码怎么写呢?
第一步:如果数组的大小为0的话,说明是空节点
第二步:如果不为空,取后序遍历最后一个元素作为节点元素
第三步:找到后序数组的最后一个元素在中序数组的位置,作为切割点
第四步:切割中序数组,切成中序左数组和中序右数组
第五步:切割后序数组,切割成后序左数组和后序右数组
第六步:递归处理左区间和右区间
*/
    if(inorder.size()==0||postorder.size()==0) return nullptr;
    return dfs(inorder,postorder);
    }
};

19.最大的二叉树

class Solution {
public:
    TreeNode *dfs(vector<int>&nums,int left,int right){
        if(left>=right) return nullptr;
        int index=left;
        for(int i=left+1;i<right;++i){
            if(nums[i]>nums[index]) index=i;
        }
        TreeNode *root=new TreeNode(nums[index]);
        root->left=dfs(nums,left,index);
        root->right=dfs(nums,index+1,right);
        return root;
    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return dfs(nums,0,nums.size());
    }
};

20.合并二叉树

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        if(root1==nullptr) return root2;
        if(root2==nullptr) return root1;
        auto merge=new TreeNode(root1->val+root2->val);
        merge->left=mergeTrees(root1->left,root2->left);
        merge->right=mergeTrees(root1->right,root2->right);
        return merge;
    }
};

21. 二叉搜索树中的搜索

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
       //一个适用于各种二叉树的方法,运行速度比较慢
       if(root==nullptr){
           return nullptr;
       }
       if(root->val==val) return root;
       TreeNode *node_left=searchBST(root->left,val);
       TreeNode *node_right=searchBST(root->right,val);
       if(node_left!=nullptr) return node_left;
       if(node_right!=nullptr) return node_right;
       return nullptr;
    }
};
class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
//迭代
    while(root!=nullptr&&root->val!=val){
        root=root->val<val? root->right:root->left;
    }
    return root;
    }
};

22.验证二叉搜索树

//

class Solution {
public:
    vector<int>res;
    void dfs(TreeNode *root){
        if(root==nullptr) return;
        dfs(root->left);
        res.push_back(root->val);
        dfs(root->right);
    }
    bool isValidBST(TreeNode* root) {
//二叉搜索树中序遍历为递增序列
    if(root==nullptr) return true;
    dfs(root);
    for(int i=1;i<res.size();++i){
        if(res[i]<=res[i-1]) return false;
    }
    return true;
    }
};
优化代码
class Solution {
public:
    long pre=LONG_MIN;//注意数据范围
    bool isValidBST(TreeNode* root) {
//验证是否为二叉搜索树:中序遍历为升序
    if(root==nullptr) return true;
    //访问左子树
    if(!isValidBST(root->left)){
        return false;
    }
    //访问根节点
    if(root->val<=pre){
        return false;
    }
    pre=root->val;
    return isValidBST(root->right);
    }
};

23.中序遍历团灭系列二叉搜索树问题

中序遍历团灭系列二叉搜索树问题
二叉搜索树一个很重要的性质:中序遍历为升序序列
1.二叉搜索树的最小绝对差

class Solution {
public:
    vector<int>res;
    int ans=INT_MAX;
    void Inorder(TreeNode *root){
        if(root==nullptr) return;
        Inorder(root->left);
        res.push_back(root->val);
        Inorder(root->right);
    }
    int getMinimumDifference(TreeNode* root) {
//注意是二叉搜索树,二叉搜索树可是有序的。
    if(root==nullptr) return  0;
    Inorder(root);
    for(int i=1;i<res.size();++i){
        ans=min(ans,res[i]-res[i-1]);
    }
    return ans;
    }
};
  1. 二叉搜索树中第k小的元素
class Solution {
public:
    vector<int>res;
    void Inorder(TreeNode *root){
        if(root==NULL) return;
        Inorder(root->left);
        res.push_back(root->val);
        Inorder(root->right);
    }
    int kthLargest(TreeNode* root, int k) {
        Inorder(root);
        sort(res.begin(),res.end());
     //使用了sort,使时间复杂度大大增加,可在中序遍历初处理
        return res[res.size()-k];
    }
};

优化:倒叙中序遍历,第k个就是所需结果

class Solution {
public:
    int res;
    void dfs(TreeNode *root,int &k){
        if(root==NULL) return;
        dfs(root->right,k);
        if(--k==0) res=root->val;
        dfs(root->left,k);
    }
    int kthLargest(TreeNode* root, int k) {
        dfs(root,k);
        return res;
    }
};

3.二叉搜索树中的众数
c++的语法还不是很熟悉啊

class Solution {
public:
    vector<int>res;
    unordered_map<int,int>map;
    void dfs(TreeNode *root,unordered_map<int,int>& map){
        if(root==nullptr) return ;
        dfs(root->left,map);
        map[root->val]++;
        dfs(root->right,map);
    }
    bool static cmp(const pair<int,int>&a,const pair<int,int>&b){
        return a.second>b.second;
    }
    vector<int> findMode(TreeNode* root) {
        if(root==nullptr) return res;
        dfs(root,map);
        vector<pair<int,int>>vec(map.begin(),map.end());
        sort(vec.begin(),vec.end(),cmp);//给频率排个序
        res.push_back(vec[0].first);
        for(int i=1;i<vec.size();++i){
            if(vec[i].second==vec[0].second) res.push_back(vec[i].first);
            else break;
        }
        return res;

    }
};

优化:中序遍历二叉搜索树是一个有序数组,给出一个有序数组,求最大频率的元素集合。

class Solution {
private:
    int count;
    int maxCount;
    TreeNode *pre;
    vector<int>res;
    void dfs(TreeNode *cur){
        if(cur==nullptr) return;
        dfs(cur->left);//左
        if(pre==nullptr){//第一个节点
            count=1;
        }else if(pre->val==cur->val){//与前一个节点数值相同
            count++;
        }else{//与前一个节点数值不同
            count=1;
        }
        pre=cur;//更新上一个节点
        if(count==maxCount){//如果和最大值相同,放入res中
            res.push_back(cur->val);
        } 
        if(count>maxCount){//如果计数大于最大值
            maxCount=count;
            res.clear();
            res.push_back(cur->val);
        }  
        dfs(cur->right);
    }
public:
//中序遍历二叉搜索树是一个有序数组,给出一个有序数组,求最大频率的元素集合。

    vector<int> findMode(TreeNode* root) {
        int count=0;    //记录元素出现的次数
        int maxCount=0;
        TreeNode *pre=nullptr;//记录前一个节点
        res.clear();
        dfs(root);
        return res;
    }
};

24.二叉树的最近公共祖先

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root == NULL)
            return NULL;
        if(root == p || root == q) 
            return root;
            
        TreeNode* left =  lowestCommonAncestor(root->left, p, q);
        TreeNode* right = lowestCommonAncestor(root->right, p, q);
       
        if(left == NULL)
            return right;
        if(right == NULL)
            return left;      
        if(left && right) // p和q在两侧
            return root;
        
        return NULL; // 必须有返回值
    }
};

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

方法一,参考 236,二叉树迭代最近公共祖先

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

26.二叉搜索树中的插入操作

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

27.删除二叉搜索树中的节点

被删除节点左右节点都有

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
/*根据二叉搜索树的性质:(主要把删除)
如果目标节点大于当前节点值,则去右子树中删除;
如果目标节点小于当前节点值,则去左子树中删除;
如果目标节点就是当前节点,分为以下三种情况:
    其无左子:其右子顶替其位置,删除了该节点;
    其无右子:其左子顶替其位置,删除了该节点;
    其左右子节点都有:其左子树转移到其右子树的最左节点的左子树上,然后右子树顶替其位置,由此删除了该节点。
*/
    if(root==nullptr) return nullptr;
    if(key>root->val) root->right=deleteNode(root->right,key);
    else if(key<root->val) root->left=deleteNode(root->left,key);
    else{
        if(!root->left) return root->right; //情况一,欲删除节点无左子
        if(!root->right) return  root->left;//情况二,欲删除节点无右子
        TreeNode *node=root->right;         //情况三,欲删除节点左右子都有
        while(node->left){                  //寻找欲删除节点右子树的最左节点
            node=node->left;
        }
        node->left=root->left;              //将欲删除节点的左子树成为其右子树的最左节点的左子树
        root=root->right;                   //将欲删除节点的右子顶替其位置,节点被删除
    }
    return root;
    }
};

28.修剪二叉搜素树

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
/*一下代码不可行,因为有些节点不能直接删除
    if(root==nullptr||root->val<low||root->val>high) return nullptr;
    root->left=trimBST(root->left,low,high);
    root->right=trimBST(root->right,low,high);
    return root;
*/
    if(root==nullptr) return nullptr;
    if(root->val<low){//注意是二叉搜索树
        TreeNode *right=trimBST(root->right,low,high);
        return right;
    }
    if(root->val>high){
        TreeNode *left=trimBST(root->left,low,high);
        return left;
    }
    root->left=trimBST(root->left,low,high);
    root->right=trimBST(root->right,low,high);
    return root;
    }
};

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

class Solution {
public:
    TreeNode * dfs(vector<int>&nums,int left,int right){
        if(left>right) return nullptr;
        //总是选择中间位置左边的数字作为根节点
        int mid=left+((right-left)/2);
        TreeNode *node=new TreeNode(nums[mid]);
        node->left=dfs(nums,left,mid-1);
        node->right=dfs(nums,mid+1,right);
        return  node;
    }
    TreeNode* sortedArrayToBST(vector<int>& nums) {
//中序遍历二叉搜素树是有序数组,分割
    TreeNode*root=dfs(nums,0,nums.size()-1);
    return root;
    }
};

30.把二叉搜索树转换为累加树

lc 538和lc1038

class Solution {
public:
//从图中可以看出累加顺序是右中左
    int pre=0;//记录前一个节点的值
    void dfs(TreeNode *root){
        if(root==nullptr) return;
        dfs(root->right);
        root->val+=pre;
        pre=root->val;
        dfs(root->left);
    }
    TreeNode* convertBST(TreeNode* root) {
    if(root==nullptr) return nullptr;
    dfs(root);
    return root;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值