经典面试题:给两个序列如何构造一棵二叉树

微信搜一搜bigsai
大家都在关注的刷题、学习数据结构和算法宝藏项目
关注回复进群即可加入力扣打卡群,欢迎划水。近期打卡:
LeetCode 98验证二叉搜素树(中序遍历)&99恢复二叉搜索树
LeetCode 100相同的树&101对称二叉树
LeetCode 102二叉树的层序遍历&103二叉树锯齿形遍历&104二叉树的最大深度

前言

在面试的过程中,我们经常会遇到一些数据结构相关的问题,很多经典问题百问不烂。而数据结构的问题中排序、链表、二叉树等问题又是经久不衰,这不,今天就分享一道关于经典的问题:给定两个序列如何构造一颗二叉树。

tips:遇到二叉树相关的问题,多半和递归有关系

从前序与中序遍历序列构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。当然也是力扣105的原题

注意:你可以假设树中没有重复的元素

例如,给出

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

分析:
给定一个前序序列和一个中序序列,且里面没有重复的元素,如何构造一和二叉树呢?我们可以先单独观察两个序列的特征:

前序遍历:遍历规则为(根,[左侧区域],[右侧区域])。
中序遍历:遍历规则为([左侧区域],根,[右侧区域])。

其中前序遍历的左侧区域和中序遍历的左侧区域包含元素的范围相同,根也是相同的。所以可以进行这样的操作:

  1. 根据前序遍历的第一个找到根节点,可以确定根
  2. 通过中序遍历找到根节点的值,这样可以知道左侧区域和右侧区域节点个数多少。
  3. 根节点左侧区域由前中序列确定的左侧区域确定,根节点的右侧节点由前中序序列的右侧区域确定。

一些操作可以借助这张图进行理解:
在这里插入图片描述

具体的实现上,可以使用一个HashMap存储中序存储的序列,避免重复计算。实现的代码为:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
   public TreeNode buildTree(int[] preorder, int[] inorder) {
		if(preorder.length==0)
			return null;
		TreeNode root=new TreeNode(preorder[0]);
		Map<Integer, Integer>map=new HashMap<Integer, Integer>();
		for(int i=0;i<inorder.length;i++)
		{
			map.put(inorder[i], i);
		}
		return buildTree(preorder,0,preorder.length-1, map,0,inorder.length-1);
    }

	private TreeNode buildTree(int[] preorder, int preStart, int preEnd, Map<Integer, Integer> map, int inStart, int inEnd) {
		// TODO Auto-generated method stub
		if(preEnd<preStart||inEnd<inStart)
			return null;
		TreeNode node=new TreeNode(preorder[preStart]);
		int i=map.get(preorder[preStart]);//节点的值
		
		int leftlen=i-inStart;//左面的长度
		node.left=buildTree(preorder, preStart+1, preStart+1+leftlen, map, inStart, i-1);
		node.right=buildTree(preorder, preStart+leftlen+1,preEnd, map, i+1, inEnd);
		return node;		
	}
}

从中序与后序遍历序列构造二叉树

根据一棵树的中序遍历与后序遍历构造二叉树,力扣106题

注意:你可以假设树中没有重复的元素。

例如,给出

中序遍历 inorder = [9,3,15,20,7]
后序遍历 postorder = [9,15,7,20,3]

返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

分析:
有了上面的分析,那么通过一个后序遍历和中序遍历去构造一棵二叉树,其实原理和前面的也是一样的。

后序遍历:遍历规则为([左侧区域],[右侧区域],根)。
中序遍历:遍历规则为([左侧区域],根,[右侧区域])。

在这里插入图片描述
具体实现的代码为:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
   public TreeNode buildTree(int[] inorder,int[] postorder) {
		if(postorder.length==0)
			return null;
		Map<Integer, Integer>map=new HashMap<Integer, Integer>();
		for(int i=0;i<inorder.length;i++)
		{
			map.put(inorder[i], i);
		}
		return buildTree(postorder,0,postorder.length-1, map,0,inorder.length-1);
    }

	private TreeNode buildTree(int[] postorder, int postStart, int postEnd, Map<Integer, Integer> map, int inStart, int inEnd) {
		// TODO Auto-generated method stub
		if(postEnd<postStart||inEnd<inStart)
			return null;
		TreeNode node=new TreeNode(postorder[postEnd]);
		int i=map.get(postorder[postEnd]);
		
			
		int leftlen=i-inStart;
		
		node.left=buildTree(postorder, postStart,postStart+leftlen-1, map, inStart, i-1);
		node.right=buildTree(postorder, postStart+leftlen,postEnd-1, map, i+1, inEnd);           return node;		
	}
}

原创不易,bigsai请你帮两件事帮忙一下:

  1. star支持一下, 您的肯定是我在平台创作的源源动力。

  2. 微信搜索「bigsai」,关注我的公众号,不仅免费送你电子书,我还会第一时间在公众号分享知识技术。加我还可拉你进力扣打卡群一起打卡LeetCode。

记得关注、咱们下次再见!

image-20201114211553660

Big sai CSDN认证博客专家 数据结构与算法 爬虫 Java
原创公众号:「bigsai」,回复【bigsai】获取珍藏pdf书籍资源,回复【进群】即可加入leetcode打卡群。主要分享Java,数据结构与算法,期待你的关注!
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页
实付 19.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值