常见二叉树题目集合

1.三种遍历方式

前序题目链接
中序题目链接
后序题目链接
在这里插入图片描述

2.二叉树的镜像

请完成一个函数,输入一个二叉树,该函数输出它的镜像。
题目链接
在这里插入图片描述

class Solution {
public:

    TreeNode* mirrorTree(TreeNode* root) {
      if(root==NULL)
        return root;

        swap(root->left,root->right);
        mirrorTree(root->left);
        mirrorTree(root->right);

        return root;
    }
};

3.对称的二叉树

请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
题目链接
在这里插入图片描述

class Solution {
public:
    bool Judge(TreeNode *left,TreeNode *right)
    {
        if(left==NULL&&right==NULL)
                return true;
        if(left==NULL||right==NULL)//不同时为空
            return false;
        
        return 
        (left->val==right->val)&&//判断当前的镜像值是否相等
        Judge(left->left,right->right)&&
        Judge(left->right,right->left);


    }
    bool isSymmetric(TreeNode* root) {
        if(!root)
        return true;
        return Judge(root->left,root->right);
    }
};

4.二叉树的深度

在这里插入图片描述

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

        int left_depth=maxDepth(root->left)+1;
        int right_depth=maxDepth(root->right)+1;

        return fmax(left_depth,right_depth);
    }
};

5.平衡二叉树

输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
题目链接

在这里插入图片描述

6.重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
题目链接
在这里插入图片描述

class Solution {
public:
TreeNode* _buildTree(vector<int>& preorder, vector<int>& inorder,int &prev_sub,int in_start,int in_end)
    {
        if(in_start>in_end)//空树
        return NULL;

        TreeNode *root=new TreeNode(preorder[prev_sub]);
        //在中序中查找,根节点
        int index=in_start;
        while(index<in_end)
        {
            if(preorder[prev_sub]==inorder[index])
                break;
            else
                index++;
        }

        if(in_start<=index-1)//左区间里面还有值
        root->left=_buildTree(preorder,inorder,++prev_sub,in_start,index-1);
        else
        root->left=NULL;

        if(index+1<=in_end)//右区间里面还有值
        root->right=_buildTree(preorder,inorder,++prev_sub,index+1,in_end);
        else
        root->right=NULL;

        return root;
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int prev_sub=0;
        return _buildTree(preorder,inorder,prev_sub,0,inorder.size()-1);
    }
};

7.树的子结构

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。
题目链接
在这里插入图片描述

class Solution {
public:
    bool _isSubStructure(TreeNode* A, TreeNode* B)//判断两棵树是否相等
    {
        if(B==NULL)
        return true;

        if(A==NULL&&B!=NULL)
        return false;

        return 
        (A->val==B->val)&&
        _isSubStructure(A->left,B->left)&&
        _isSubStructure(A->right,B->right);
    }
    bool isSubStructure(TreeNode* A, TreeNode* B) {
        
        if(A==NULL||B==NULL)//遍历完了,还没有找到对应的结构
         return false;

       if(_isSubStructure(A,B))
       return true;

        return isSubStructure(A->left,B)||isSubStructure(A->right,B);//遍历A
    }
};

8.从上至下打印二叉树I

从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
题目链接

在这里插入图片描述

class Solution {
public:
    vector<int> ret;
    queue<TreeNode*>q;
    vector<int> levelOrder(TreeNode* root) {
        if(root==NULL)
        return ret;
        
        q.push(root);
        while(!q.empty())
        {
            TreeNode *root=q.front();
            q.pop();
            
            ret.push_back(root->val);
            
            if(root->left!=NULL)
                q.push(root->left);
            if(root->right!=NULL)
                q.push(root->right);
        }
        return ret;
    }
};

9.从上至下打印二叉树II

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
题目链接
在这里插入图片描述

class Solution {
public:

    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> ret;
        queue<TreeNode*> q1;
        queue<TreeNode*> q2;

        if(root==NULL)
        return ret;

        q1.push(root);
        while(!q1.empty()||!q2.empty())
        {
            vector<int> temp1;
            while(!q1.empty())
            {
                TreeNode *root=q1.front();
                q1.pop();
                temp1.push_back(root->val);

                if(root->left!=NULL)
                    q2.push(root->left);
                if(root->right!=NULL)
                    q2.push(root->right);
            }
            ret.push_back(temp1);

            vector<int> temp2;
            while(!q2.empty())
            {
                TreeNode *root=q2.front();
                q2.pop();
                temp2.push_back(root->val);
                
                if(root->left!=NULL)
                    q1.push(root->left);
                if(root->right!=NULL)
                    q1.push(root->right);
            }
            if(temp2.size()!=0)
            ret.push_back(temp2);
        }

        return ret;


    }
};

10.从上至下打印二叉树III

请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
题目链接
在这里插入图片描述

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> ret;
        stack<TreeNode*> st1;
        stack<TreeNode*> st2;

        if(root==NULL)
        return ret;

        st1.push(root);

        while(!st1.empty()||!st2.empty())
        {
            vector<int> temp1;
            while(!st1.empty())
            {
                TreeNode *root=st1.top();
                st1.pop();
                temp1.push_back(root->val);

                //从左至右放入st2之中
                if(root->left)
                st2.push(root->left);
                if(root->right)
                st2.push(root->right);
            }
            ret.push_back(temp1);

            vector<int> temp2;
            while(!st2.empty())
            {
                TreeNode *root=st2.top();
                st2.pop();
                temp2.push_back(root->val);

                //从右至左放入st1之中
                if(root->right)
                st1.push(root->right);
                if(root->left)
                st1.push(root->left);
            }
            if(temp2.size()!=0)
            ret.push_back(temp2);
        }
        return ret;
    }
 
};

11.二叉树中和为某一值的路径

输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。
题目链接
在这里插入图片描述

class Solution {
public:
void _pathSum(TreeNode* root, int target,vector<vector<int>> &ret,vector<int> &temp,int sum)
{
    if(root==NULL)
        return ;

    temp.push_back(root->val);
    sum+=root->val;
    if(sum==target&&root->left==NULL&&root->right==NULL)
    ret.push_back(temp);

    _pathSum(root->left, target,ret,temp,sum);
    _pathSum(root->right, target,ret,temp,sum);
    temp.pop_back();//回溯
}
    vector<vector<int>> pathSum(TreeNode* root, int target) {
        vector<vector<int>> ret;
        vector<int> temp;
        int sum=0;
    _pathSum(root, target,ret,temp,sum);
    return ret;
    }
};

12. 二叉搜索树的第k大节点

给定一棵二叉搜索树,请找出其中第k大的节点。
题目链接
在这里插入图片描述

class Solution {
public:
    void _kthLargest(TreeNode* root, int &k,int &ret)
    {
        if(root==NULL||k==0)//为空或者K=0都不需要再进行下去
        return ;
        _kthLargest(root->right,k,ret);
        k--;//当前访问到了一个节点,统计数减1
        if(k==0)
        {
            ret=root->val;
            return ;
        }
        _kthLargest(root->left,k,ret);
    }
    int kthLargest(TreeNode* root, int k) {
        int ret=0;
        _kthLargest(root,k,ret);
        return ret;
    }
};

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

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
题目链接
在这里插入图片描述

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {

        while(root->val>p->val&&root->val>q->val||root->val<p->val&&root->val<q->val)
        {
            if(root->val>p->val)//比两个节点的值都大,则往左边走
                root=root->left;
             else if(root->val<p->val)//比两个节点的值都小,则往右边走
                root=root->right;
        }
        //此时,刚刚好,root等于其中一个节点,或者节点位于root的一左一右
        return root;
    }
};

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

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

题目链接
在这里插入图片描述

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root==NULL)
        return 0;

        if(root==p||root==q)
        return root;

        TreeNode *left_node=lowestCommonAncestor(root->left,p,q);
        TreeNode *right_node=lowestCommonAncestor(root->right,p,q);

        if(left_node==NULL)//左边为空则都在右侧
        return right_node;
        
        if(right_node==NULL)//右侧为空则在左侧
        return left_node;

        return root;//都不为空,则当前节点就是根节点
    }
};

15.不同的二叉搜索树

给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
在这里插入图片描述

class Solution {
public:
    int numTrees(int n) {
        vector<int> ret(n+1,0);
        ret[0]=1;//0棵树时,为空时一种情况
        ret[1]=1;//一颗树时一种情况

        if(n<2)
        return ret[n];
        
        ret[2]=2;//两棵树时两种情况

        // ret[i]=ret[i-1]*ret[0]+ret[i-2]*ret[1] +....+ ret[0]*ret[i-1]

        for(int i=3;i<=n;i++)
        {
            for(int j=0;j<i;j++)
            {
                ret[i]+= ret[j]*ret[i-j-1];
            }
        }
        return ret[n];
    }
};

16.二叉树中的最大路径和

路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。
路径和 是路径中各节点值的总和。
给你一个二叉树的根节点 root ,返回其 最大路径和 。
题目链接

采用后序遍历的方式:

class Solution {
public:
    int _maxPathSum(TreeNode* root,int &count) 
    {
        if(root==nullptr)
            return 0;
        int left=_maxPathSum(root->left,count);
        int right=_maxPathSum(root->right,count);
        int val=root->val;
    //找出当前子树路径最大值
        int temp1=val+left+right;
        int temp2=val+left;
        int temp3=val+right;
        int temp4=fmax(temp1,fmax(temp2,temp3));
    //记录下来
        count=fmax(temp4,count);
    //判断对上层是否有贡献
        if(temp2<0&&temp3<0)
        {
            if(val<0)
            return 0;
            return val;
        }
        return fmax(temp2,temp3);
    }

    int maxPathSum(TreeNode* root) {
        int count=root->val;
        _maxPathSum(root,count);
        return count;
    }
};

17.从中序与后序遍历序列构造二叉树

根据一棵树的中序遍历与后序遍历构造二叉树。
题目链接
在这里插入图片描述

class Solution {
public:
    TreeNode* _buildTree(vector<int>&inorder,vector<int>&postorder,int &pos,int begin,int end)
    {
        int index=begin;
        while(index<end)
        {
            if(inorder[index]!=postorder[pos])//在中序之中寻找
                index++;
            else
                break;
        }
        //构造根节点
            TreeNode* root=new TreeNode(postorder[pos]);
        //划分区间,构建左右子树
        if(index+1<=end)
            root->right=_buildTree(inorder,postorder,--pos,index+1,end);//构造右子树
        if(begin<=index-1)
            root->left=_buildTree(inorder,postorder,--pos,begin,index-1);//构造左子树
        
        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        int pos=postorder.size()-1;
        if(pos<0)//空树
            return nullptr;
        return _buildTree(inorder,postorder,pos,0,inorder.size()-1);
    }
};

18.从前序与中序遍历序列构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。
题目链接
在这里插入图片描述

class Solution {
public:
    TreeNode* _buildTree(vector<int>&preorder,vector<int>&inorder,int &prev,int begin,int end)
    {
        if(begin>end)   
            return nullptr;
        
        int index=begin;
        while(index<end)
        {
            if(inorder[index]!=preorder[prev])
                index++;
            else
                break;
        }
        //构造根节点
        TreeNode* root=new TreeNode(preorder[prev]);

        //构造左右子树
        if(index>begin)//构造左区间
            root->left=_buildTree(preorder,inorder,++prev,begin,index-1);
        if(index<end)
            root->right=_buildTree(preorder,inorder,++prev,index+1,end);
        
        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int prev=0;
        return _buildTree(preorder,inorder,prev,0,inorder.size()-1);
    }
};

19.二叉树与双向链表

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
题目链接
在这里插入图片描述

class Solution {
public:
    void _Convert(TreeNode* root,TreeNode*& prev)
    {
      if(root==nullptr)
          return ;
      _Convert(root->left,prev);
      
      root->left=prev;     
      if(prev)
        prev->right=root;
      
      prev=root;
      _Convert(root->right,prev);
    }
    TreeNode* Convert(TreeNode* pRootOfTree) {
      TreeNode *prev=nullptr;
      if(pRootOfTree==nullptr)
         return nullptr;
      TreeNode* head=pRootOfTree;
      while(head->left)//不断往左走,找到头节点
      {
        head=head->left;
      }
      _Convert(pRootOfTree,prev);
      return head;
      
        
    }
};

20. 二叉树的层序遍历||

给定一个二叉树,返回其节点值自底向上的层序遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
题目链接
在这里插入图片描述

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        vector<vector<int>> ret;
        if(root==nullptr)
            return ret;
        queue<TreeNode*>q;
        q.push(root);
        int count=1;
        while(!q.empty())
        {
            vector<int> temp;
            while(count--)
            {
                TreeNode *node=q.front();
                temp.push_back(node->val);
                q.pop();
                //下一层入队列
                if(node->left)
                    q.push(node->left);
                if(node->right)
                    q.push(node->right);
            }
            count=q.size();
            ret.push_back(temp);
        }
        reverse(ret.begin(),ret.end());
        return ret;
    }
};

21.根据二叉树创建字符串

题目链接
在这里插入图片描述

class Solution {
public:
    void _tree2str(TreeNode *root,string &str)
    {
        if(root==nullptr)
            return;
        str+=to_string(root->val);//加入值

        if(root->left==nullptr&&root->right==nullptr)//左右孩子都为空
            return ;
        
        str+='(';//左孩子括号始终要加上
        _tree2str(root->left,str);
        str+=')';

        if(root->right==nullptr)
            return ;
        str+='(';
        _tree2str(root->right,str);
        str+=')';
    }
    string tree2str(TreeNode* root) {
        string str;
        if(root==nullptr)
            return str;
        _tree2str(root,str);
        return str;
    }
};

22.非递归前序遍历

题目链接
在这里插入图片描述

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int>ret;
        TreeNode *Left=nullptr;
        if(root)
        {
            st.push(root);
            ret.push_back(root->val);
            Left=root->left;
        }
        while(!st.empty()||Left)
        {
            while(Left)//左子树不为空则一直走下去
            {
                ret.push_back(Left->val);
                st.push(Left);//将左子树入栈
                Left=Left->left;
            }
            //此时左子树全部走完,开始走右子树
            Left=st.top()->right;
            st.pop();
        }
        return ret;
    }
};

23.非递归中序遍历

中序遍历的方式是:左、根、右 -> 因此可以先将全部的根节点入栈 ->再取出来打印,获取其右子树

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int>ret;
        stack<TreeNode*>st;
        TreeNode* Left=nullptr;
        if(root)
        {
            st.push(root);
            Left=root->left;
        }
        while(!st.empty()||Left)
        {
            while(Left)
            {
                st.push(Left);//入栈
                Left=Left->left;//往左走
            }
            //此时左节点全在栈中
            Left=st.top();//从栈中拿值
            st.pop();
            ret.push_back(Left->val);//存值
            Left=Left->right;//往右走
        }
        return ret;
    }
};

24.非递归后续遍历

在这里插入图片描述

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> ret;
        stack<TreeNode*>st;
        TreeNode* prev=nullptr;//记录上一个被访问过的节点
        TreeNode* Left=nullptr;
        if(root)
        {
            st.push(root);
            Left=root->left;
        }
        while(!st.empty()||Left)
        {
            while(Left)//将左子树全部入栈
            {
                st.push(Left);
                Left=Left->left;
            }
            TreeNode* node=st.top();//从栈中获取节点

            if(node->right==nullptr||node->right==prev)//右子树为空,或者已经访问过了
            {
                ret.push_back(node->val);
                prev=node;//记录下来
                st.pop();//出栈
            }
            else
                Left=node->right;//否则获取该节点的右子树
        }
        return ret;
    }
};
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值