剑指offer笔试刷题(1):树专题

1.输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)遍历A找到与B根结点相同的位置,子结构是从根结点到叶子节点相同。

思路1:1.先考虑特殊情况,如果指针为空则错误。2定义一个子函数,功能是判断是否是子结构,然后主函数从根结点到叶子结点遍历。3return 递归的布尔型值,如果最后return的是&& 则递归终止条件是true关系不大,只要有一个是false,return的就是false.return的是||则递归终止条件是false关系不大。

【通过率百分之55.56%】

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
class Solution {
public:
    bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
    {
        if(pRoot2==NULL||pRoot1==NULL)
            return false;
       if(pRoot1->val==pRoot2->val&&isbufen(pRoot1,pRoot2))
           return true;
        else 
            return HasSubtree(pRoot1->left,pRoot2)||HasSubtree(pRoot1->right,pRoot2);
    }
    bool isbufen(TreeNode* p1,TreeNode* p2)  //定义子函数完成确实是否是子结构的任务
    {
        if(p2==NULL)
            return true;
        if(p1==NULL)
            return true;
        if(p1->val!=p2->val)
            return false;
        if(p1-)
        return isbufen(p1->left,p2->left) && isbufen(p1->right,p2->right);
           
    }
};

2.二叉树的镜像:操作给定的二叉树,将其变换为源二叉树的镜像。

困惑:1.函数类型为void 则只返回return .2.何时申请结点指针的内存空间。

思路:递归终止条件是结点为空

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
class Solution {
public:
    void Mirror(TreeNode *pRoot) {
        if(pRoot==NULL)
            return;
        TreeNode* tmp;
        tmp=pRoot->left;
        pRoot->left=pRoot->right;
        pRoot->right=tmp;
        Mirror(pRoot->left);
        Mirror(pRoot->right);

    }
};

3.从上往下打印二叉树:从上往下打印出二叉树的每个节点,同层节点从左至右打印。

思路:1定义指针类型的队列,做到按层遍历,先进先出.

扫描二维码关注公众号,回复: 3710705 查看本文章

struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
class Solution {
public:
    vector<int> PrintFromTopToBottom(TreeNode* root) {
        //stack stc1;
        vector<int> que;
        queue<TreeNode*> q1;
        TreeNode* fr;
        if(root==NULL)
            return que;
        que.push_back(root->val);
        q1.push(root);
        while(!q1.empty())
        {
            fr=q1.front();
            //que.push_back(fr->val);
            if(fr->left!=NULL)
            {
            que.push_back(fr->left->val);
            q1.push(fr->left);}
            if(fr->right!=NULL)
            {
                que.push_back(fr->right->val);
                q1.push(fr->right);
            }
            q1.pop();
        }
        return que;
    }
};

4.重建二叉树:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

思路:前序遍历根结点在第一位,而中序遍历根结点在中间。所以找出前序遍历第一个值在中序遍历中的位置,将两个遍历分割为前序和中序的左右子树,做递归,递归的终止条件是子树为空。2递归,树的结构通过函数返回来传承。

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    
    
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        int inlen=pre.size();
        if(inlen==0)
            return NULL;
        TreeNode *node=new TreeNode(pre[0]);
        int i=0,j;
        vector<int> lpretree,lvintree;
        vector<int> rpretree,rvintree;
        //node->val=pre[0];
        int gen=0;
        for(j=0;j<inlen;j++)
        {
            if(vin[j]==pre[0])
            {
                gen=j;
                break;
            }
        }
        for(j=0;j<gen;j++)
        {
                lvintree.push_back(vin[j]);
                lpretree.push_back(pre[j+1]);

        }
        for(j=gen+1;j<vin.size();j++) //如何构建树的结构,节点之间怎么连接。
        {
            rvintree.push_back(vin[j]);
            rpretree.push_back(pre[j]);
        }
        node->left=reConstructBinaryTree(lpretree,lvintree);
        node->right=reConstructBinaryTree(rpretree,rvintree);
        return node; 
    }
};

5.二叉搜索树的后序遍历:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。(通过率62.5%,改错困难)

思路:通过递归。后序遍历,二叉搜索树根结点在最后,前一部分都比根结点小,后一部分比根结点大。通过递归,将遍历一步步分割直至分完。递归中止条件为分完为空为止。

class Solution {
public:
    bool VerifySquenceOfBST(vector<int> sequence) {
        if(dfs(sequence,0,sequence.size()-1))
            //cout>>"Yes";
        {cout<<"Yes"<<endl;
          return true;}
            
        else 
           {cout<<"NO"<<endl;
            return false;}
    }
    bool dfs(vector<int> sequence,int left,int right){
        if(!sequence.empty())
            
           return true;
        left=0;
        right=sequence.size()-1;
        if(left>=right)
            return false;
        vector<int> lseq,rseq;
        int gsize=sequence.size();
        int gen=sequence[gsize-1];
        if(gsize<=2)
            return true;
        
        while(left<right)
        {
            if(sequence[left]<gen)
            {
                lseq.push_back(sequence[left]);
                left++;
            }
            
            if(sequence[right]>gen)
            {
                rseq.push_back(sequence[right]);
                right--;
            }
            
            
         }
        if(right!=left+1)
            return false;
        return dfs(lseq,0,lseq.size()-1)&& dfs(rseq,0,rseq.size()-1);
            
        
        
    }
};

6.二叉树和为某一值的路径:输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

思路:1递归,每到一部根结点判断和目标值的差距,比目标值小就到子节点2.递归终止条件,当到叶子结点就停止。

困惑:困惑处是容器内部的排序,以及怎么递归的给容器添值。

[错误的程序]

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
class Solution {
public:
    vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
        vector<int> res,res1;
        vector<vector<int>> res2;
        res1=dfs(res,root,expectNumber);
        if(res1.size()>0)
          res2.push_back(res1);
        return res2;
        } 
    vector<int> dfs(vector<int> res,TreeNode* root,int Num){
        //vector<int> res; 不能每次都新建res
        //
        if(root==NULL)
            return res;
        
        if(root->val>Num)
        {
            res.clear();
            return res;
        }
            
        if(root->val==Num&& root->left==NULL&&root->right==NULL)
        {
            res.push_back(root->val);
            return res;
        }
            
        if(root->val<Num&&(root->left!=NULL||root->right!=NULL))
        {
            res.push_back(root->val);
            dfs(res,root->left,Num-root->val);
            dfs(res,root->right,Num-root->val);
        }
        if(root->val<Num&&root->left==NULL&&root->right==NULL)
        {
            res.clear();
             return res;
        } 
       }    
};
        
    
7.二叉树的深度:输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。

困惑:困惑是在于怎么返回最大的路径数值,返回值怎么和深度结合起来,函数返回类型是int,不能定义一个int的变量,那样向下遍历需要为多个分支定义多个变量。递归终止条件(第一个考虑的)是结点为空。返回0,返回加一,取max值。(要点是利用好函数返回和递归)   

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
class Solution {
public:
    int TreeDepth(TreeNode* pRoot)
    {
    if(pRoot==NULL)
        return 0;
    if(pRoot->left==NULL&&pRoot->right==NULL)
        return 1;
        int inpRootleft,inpRootright;
    if(pRoot->left!=NULL)
         inpRootleft=1+TreeDepth(pRoot->left);
    if(pRoot->right!=NULL)
         inpRootright=1+TreeDepth(pRoot->right);
     return max(inpRootleft,inpRootright);
     
    }
}; 

猜你喜欢

转载自blog.csdn.net/weixin_35837473/article/details/82989892