• 树常考题型


    1.输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

    思路:先通过先序遍历找到两棵树根节点相等得节点,然后进行从这两个节点开始递归判断是不是子结构。

    class Solution {
    public:
        bool HasSubtree(TreeNode* root1, TreeNode* root2)
        {
            bool result = false;
                if(root1 != NULL && root2 != NULL){
                    if(root1->val == root2->val){
                        result = DoesTree1HaveTree2(root1,root2);
                    }
                    if(!result){result = HasSubtree(root1->left, root2);}
                    if(!result){result = HasSubtree(root1->right, root2);}
                }
                return result;
        }
    
    bool DoesTree1HaveTree2(TreeNode* root1, TreeNode* root2) {
        if(root1 == NULL && root2 != NULL) return false;
        if(root2 == NULL) return true;
        if(root1->val != root2->val) return false;
        return DoesTree1HaveTree2(root1->left, root2->left) && DoesTree1HaveTree2(root1->right, root2->right);
    }
    
    };

     2.求一棵树的镜像

    思路:先序遍历这棵树的每个节点,如果遍历到的节点有子节点,就交换它的两个子节点。

    class Solution {
    public:
        void Mirror(TreeNode *pRoot) {
            if(!pRoot)return;
            if(pRoot->left==NULL&&pRoot->right==NULL)return;
            TreeNode* tmp=pRoot->left;
            pRoot->left=pRoot->right;
            pRoot->right=tmp;
            if(pRoot->left)Mirror(pRoot->left);
            if(pRoot->right)Mirror(pRoot->right);
        }
    };

     3.给你一个序列,判断该序列是不是二叉排序树的后序遍历

    思路:后序遍历中最后一个数字是树得跟节点的值,序列前面的数可以分成两部分,前一部分比该值小,后一部分比该值大。

    class Solution {
    public:
        bool VerifySquenceOfBST(vector<int> sequence) {
            if(sequence.size()==0)return false;
            return help(sequence,0,sequence.size()-1);
        }
        bool help(vector<int>sequence,int start,int end){
            if(start>=end)return true;
            int i=start;
            int value=sequence[end];
            while(sequence[i]<value){
                i++;
            }
            for(int j=i;j<end;j++){
                if(sequence[j]<value){
                    return false;
                }
            }
            return help(sequence,start,i-1)&&help(sequence,i,end-1);
            }
    };

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

    思路:dfs,记住root->left前一定要先判断(if(root->left))

    class Solution {
    public:
        vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
            vector<int>out;
            vector<vector<int>>res;
            if(!root)return res;
            help(root,expectNumber,res,out);
            return res;
        }
        
        void help(TreeNode* root,int number,vector<vector<int>>&res,vector<int>&out){
            out.push_back(root->val);
            if(root->left==NULL&&root->right==NULL){
                if(number==root->val)res.push_back(out);
            }
            if(root->left){
                help(root->left,number-root->val,res,out);
            }
            if(root->right){
                help(root->right,number-root->val,res,out);
            }
            out.pop_back();
        }
    };

    5.树的深度(非递归)

    思路:利用队列层次遍历

    class Solution {
    public:
        int TreeDepth(TreeNode* pRoot)
        {
            if(!pRoot)return 0;
            queue<TreeNode*>q;
            q.push(pRoot);
            int depth=0;
            while(!q.empty()){
                int size=q.size();
                for(int i=0;i<size;i++){
                    if(q.front()->left)q.push(q.front()->left);
                    if(q.front()->right)q.push(q.front()->right);
                    q.pop();
                }
                depth++;
            }
            return depth;
        }
    };

    6.判断一棵二叉树是不是平衡二叉树

    思路:利用后序遍历从下到上求每个节点左右子树的高度差,这样可以省去一些重复节点的遍历

    class Solution {
    public:
        bool IsBalanced_Solution(TreeNode* pRoot) {
            bool flag=true;
            int tmp=getDepth(pRoot,flag);
            return flag;
        }
        
        int getDepth(TreeNode* root,bool &flag){
            if(!root)return 0;
            int left=getDepth(root->left,flag);
            int right=getDepth(root->right,flag);
            if(abs(left-right)>1)flag=false;
            
            return left>right?left+1:right+1;
        }
    };

    7.按之字形打印二叉树

    思路:利用两个栈来接收每行的节点,并且用一个标志位判断是从左向右还是从又向左

    class Solution {
    public:
        vector<vector<int> > Print(TreeNode* pRoot) {
            vector<vector<int>>res;
            if(!pRoot)return res;
            vector<int>temp;
            int flag=0;//0是向右,1是向左
            stack<TreeNode*>s1;
            stack<TreeNode*>s2;
            s1.push(pRoot);
            while(!s1.empty()||!s2.empty()){
                if(!s1.empty()){
                    const int size=s1.size();
                    for(int i=0;i<size;i++){
                        if(flag==0){
                            if(s1.top()->left)s2.push(s1.top()->left);
                            if(s1.top()->right)s2.push(s1.top()->right);
                        }
                        else{
                            if(s1.top()->right)s2.push(s1.top()->right);
                            if(s1.top()->left)s2.push(s1.top()->left);
                        }
                        temp.push_back(s1.top()->val);
                        s1.pop();
                        }
                    res.push_back(temp);
                    temp.clear();
                    flag=!flag;
                   }
                else if(!s2.empty()){
                    const int size=s2.size();
                    for(int i=0;i<size;i++){
                        if(flag==0){
                            if(s2.top()->left)s1.push(s2.top()->left);
                            if(s2.top()->right)s1.push(s2.top()->right);
                        }
                        else{
                            if(s2.top()->right)s1.push(s2.top()->right);
                            if(s2.top()->left)s1.push(s2.top()->left);
                        }
                        temp.push_back(s2.top()->val);
                        s2.pop();
                        }
                    res.push_back(temp);
                    temp.clear();
                    flag=!flag;
                   }
                }
            return res;
        }
    };

     8.给定一棵二叉搜索树,请找出其中的第k小的结点。例如,(5,3,7,2,4,6,8)中,按结点数值大小顺序第三小结点的值为4。

    思路:二叉搜索树的中序遍历是排序的,我们根据中序遍历找到第k个小个节点。

    class Solution {
    public:
        TreeNode* KthNode(TreeNode* pRoot, int k)
        {
            if(!pRoot)return NULL;
            stack<TreeNode*>ss;
            TreeNode* cur=pRoot;
            int count=0;
            while(cur||!ss.empty()){
                if(cur){
                    ss.push(cur);
                    cur=cur->left;
                }
                else{
                    cur = ss.top();
                    count++;
                    if(count==k)
                        return cur;
                    ss.pop();
                    cur = cur->right;
                }
            }
            return NULL;
        }
    };

     9.二叉树中的最大路径和(思路:参考https://www.cnblogs.com/grandyang/p/4280120.html

    class Solution {
    public:
        int maxv=INT_MIN;
        int maxPathSum(TreeNode* root) {
            if(root==NULL)
                return 0;
            calc(root);
            return maxv;
        }
        
        int calc(TreeNode* root)
        {
            if(root==NULL)
                return 0;
            int temp=root->val;
            int lmaxsum=calc(root->left);
            int rmaxsum=calc(root->right);
            
            if(lmaxsum>0)
                temp+=lmaxsum;
            if(rmaxsum>0)
                temp+=rmaxsum;
            if(temp>maxv)
                maxv=temp;
            //返回以当前节点为根节点的子树的和
            return max(root->val,max(root->val+lmaxsum,root->val+rmaxsum));//因为对于当前节点root来说,它的上一个节点只可能选择root+left与root+right中的最大值
                
        }
    };

      10.二叉树中的最近公共祖先

    链接:https://www.cnblogs.com/inception6-lxc/p/9100151.html

  • 相关阅读:
    【原】csv文件导入MySQL数据库的实践
    【原】两个时间相加的运算符重载实现
    【转】趣味题:"Hello,world"的输出
    【转】WordPress源码解读(3)
    轻松记住大端小端的含义(附对大端和小端的解释)
    《编程精粹》书摘与读书笔记
    malloc/free函数的简单实现及思考
    如何写出正确的二分查找?——利用循环不变式理解二分查找及其变体的正确性以及构造方式
    Essential C++学习笔记备忘
    Linux中随手可得的测试、调试、性能检验工具
  • 原文地址:https://www.cnblogs.com/inception6-lxc/p/9439763.html
Copyright © 2020-2023  润新知