描述
请根据二叉树的前序遍历,中序遍历恢复二叉树,并打印出二叉树的右视图
示例1
输入:
[1,2,4,5,3],[4,2,5,1,3]
复制返回值:
[1,3,5]
复制
备注:
二叉树每个节点的值在区间[1,10000]内,且保证每个节点的值互不相同。
对于任意一颗树而言,前序遍历的形式总是
[ 根节点, [左子树的前序遍历结果], [右子树的前序遍历结果] ]
即根节点总是前序遍历中的第一个节点。而中序遍历的形式总是
[ [左子树的中序遍历结果], 根节点, [右子树的中序遍历结果] ]
-
用Map保存中序遍历的值和对应索引,关键可以快速定位每一次根结点的位置
-
在中序遍历中定位到根节点,知道左子树和右子树中的节点数目。由于同一颗子树的前序遍历和中序遍历的长度显然是相同的,因此我们就可以对应到前序遍历的结果中,
对上述形式中的所有左右括号进行定位。 -
递归地构造出左子树和右子树,再将这两颗子树接到根节点的左右位置。
递归终止条件:当子树先序遍历为空,说明已经越过叶子结点,此时返回null
再通过层序遍历,从左往右,一次入队一层的结点,将每一层结点的最右边结点添加到ArrayList中,因为数组长度需要可以动态扩展,因此先用ArrayList,后面将ArrayList转换为数组
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 求二叉树的右视图
* @param xianxu int整型一维数组 先序遍历
* @param zhongxu int整型一维数组 中序遍历
* @return int整型一维数组
*/
Map<Integer,Integer>map=new HashMap();
public int[] solve (int[] xianxu, int[] zhongxu) {
// write code here
for(int i=0;i<zhongxu.length;i++)
{
map.put(zhongxu[i],i);// 用Map保存中序遍历的值和对应索引
}
TreeNode root=build(xianxu,0,xianxu.length-1,zhongxu,0,zhongxu.length-1);
return bfs(root);
}
TreeNode build(int[]xianxu,int xstart,int xend,int[]zhongxu,int zstart,int zend)
{
if(xstart>xend)return null;
int rootval=xianxu[xstart];
int index=map.get(rootval);//快速定位每一次根结点的位置
int length=index-zstart;
TreeNode root=new TreeNode(rootval);//构造根结点
root.left=build(xianxu,xstart+1,xstart+length,zhongxu,zstart,index-1);//递归构造左子树
root.right=build(xianxu,xstart+length+1,xend,zhongxu,index+1,zend);//递归构造右子树
return root;
}
int[] bfs(TreeNode root)
{
if(root==null)return null;
Deque<TreeNode>dq=new LinkedList<>();
List<Integer>list=new ArrayList<>();
dq.offer(root);
for(TreeNode temp=root;!dq.isEmpty();)
{
//每一层结点数不同,因此队列的大小是不断变化的
for(int size=dq.size();size>0;size--){
//每次出队一个结点
temp=dq.poll();
if(temp.left!=null)dq.offerLast(temp.left);
if(temp.right!=null)dq.offerLast(temp.right);
}
//数组添加的是每一层最后出队的结点,即最右边的结点
list.add(temp.val);
}
return list.stream().mapToInt(Integer::valueOf).toArray();
}
}