算法题解——请根据二叉树的前序遍历,中序遍历恢复二叉树,并打印出二叉树的右视图

根据二叉树的前序遍历和中序遍历,通过递归重构二叉树,并实现打印二叉树的右视图。输入前序遍历和中序遍历,返回二叉树的右视图节点值。示例输入[1,2,4,5,3],[4,2,5,1,3],返回[1,3,5]。" 103821709,7572385,JavaScript数组方法详解,"['javascript', 'js', '数组', '数组方法']

请根据二叉树的前序遍历,中序遍历恢复二叉树,并打印出二叉树的右视图

题目描述如下:
请根据二叉树的前序遍历,中序遍历恢复二叉树,并打印出二叉树的右视图
输入:[1,2,4,5,3],[4,2,5,1,3]
返回值:[1,3,5]

本题目可以分为两个部分

  1. 重构二叉树
  2. 打印二叉树的右视图

1、重构二叉树思路
对于先序遍历而言,[1,2,4,5,3],列表中的1必定是二叉树的根节点,而中序遍历是左子树、根节点、右子树的顺序,故在[4,2,5,1,3]中根节点1的左边[4,2,5]就是左子树,而【3】就是右子树。
我们可以根据中序遍历的列表求得左右子树的节点数目,从而在先序遍历的列表中得到左右子树的先序遍历。

如示例[1,2,4,5,3],[4,2,5,1,3];
根节点 【1】
左子树的先序遍历【2,4,5】,中序遍历【4,2,5】
右子树的先序遍历【3】,中序遍历【3】
层层递归来构建二叉树。

TreeNode* buildTree(vector<int>& xianxu,int xianxu_l,int xianxu_r,
                        vector<int>& zhongxu,int zhongxu_l,int zhongxu_r)
    {
        if(xianxu_l>xianxu_r || zhongxu_l>zhongxu_r)
            return nullptr;
        TreeNode* root = new TreeNode(xianxu[xianxu_l]);    //构建节点
        int rootIndex = 0;    //用来保存根节点在中序遍历列表的下标
        //寻找根节点
        for(int i=zhongxu_l;i<=zhongxu_r;i++)
        {
            if(zhongxu[i] == xianxu[xianxu_l])
            {
                rootIndex = i;
                break;
            }
        }
        int leftSize = rootIndex - zhongxu_l;    //左子树大小
        int rightSize = zhongxu_r - rootIndex;    //右子树大小
        //递归构建左子树和右子树
        root->left = buildTree(xianxu,xianxu_l+1,xianxu_l+leftSize,
                              zhongxu,zhongxu_l,zhongxu_l+leftSize-1);
        root->right = buildTree(xianxu,xianxu_r-rightSize+1,xianxu_r,
                               zhongxu,rootIndex+1,zhongxu_r);
        return root;
    }

2、打印输出二叉树的右视图
二叉树的右视图就是站在二叉树的右边,能看到的节点。如下图
在这里插入图片描述
此二叉树的右视图为【3,20,7】
其实本体并没有想象中的那么复杂,思路如下:
如果我们按层序遍历二叉树,每一层都按照先遍历左节点,再遍历右节点的顺序,那么每一层最后遍历的一个节点就是右视图的节点

//采用左右层序遍历,每一层最后一个节点就是右视图
    vector<int> rightView(TreeNode* root)
    {
        vector<int> res;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty())
        {
            int size = q.size();
            while(size--)
            {
                TreeNode* temp = q.front();
                q.pop();              
                if(temp->left) q.push(temp->left);
                if(temp->right) q.push(temp->right);
                if(size==0) res.push_back(temp->val);
            }
        }
        return res;       
    }

完整解题代码如下:


class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 求二叉树的右视图
     * @param xianxu int整型vector 先序遍历
     * @param zhongxu int整型vector 中序遍历
     * @return int整型vector
     */
    vector<int> solve(vector<int>& xianxu, vector<int>& zhongxu) {
        // write code here
        TreeNode* root = buildTree(xianxu,0,xianxu.size()-1,
                                  zhongxu,0,zhongxu.size()-1);
        return rightView(root);
    }
    TreeNode* buildTree(vector<int>& xianxu,int xianxu_l,int xianxu_r,
                        vector<int>& zhongxu,int zhongxu_l,int zhongxu_r)
    {
        if(xianxu_l>xianxu_r || zhongxu_l>zhongxu_r)
            return nullptr;
        TreeNode* root = new TreeNode(xianxu[xianxu_l]);    //构建节点
        int rootIndex = 0;    //用来保存根节点在中序遍历列表的下标
        //寻找根节点
        for(int i=zhongxu_l;i<=zhongxu_r;i++)
        {
            if(zhongxu[i] == xianxu[xianxu_l])
            {
                rootIndex = i;
                break;
            }
        }
        int leftSize = rootIndex - zhongxu_l;    //左子树大小
        int rightSize = zhongxu_r - rootIndex;    //右子树大小
        //递归构建左子树和右子树
        root->left = buildTree(xianxu,xianxu_l+1,xianxu_l+leftSize,
                              zhongxu,zhongxu_l,zhongxu_l+leftSize-1);
        root->right = buildTree(xianxu,xianxu_r-rightSize+1,xianxu_r,
                               zhongxu,rootIndex+1,zhongxu_r);
        return root;
    }
    
    //采用左右层序遍历,每一层最后一个节点就是右视图
    vector<int> rightView(TreeNode* root)
    {
        vector<int> res;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty())
        {
            int size = q.size();
            while(size--)
            {
                TreeNode* temp = q.front();
                q.pop();              
                if(temp->left) q.push(temp->left);
                if(temp->right) q.push(temp->right);
                if(size==0) res.push_back(temp->val);
            }
        }
        return res;       
    }
    
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值