树常考题型

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

原文地址:https://www.cnblogs.com/inception6-lxc/p/9439763.html