[算法学习]输入遍历重建二叉树

32 篇文章 0 订阅
29 篇文章 10 订阅

问题描述:
假设二叉树中的值都不重复,
(1) 输入前序遍历和中序遍历的结果,输出该二叉树;
(2) 输入中序遍历和后序遍历的结果,输出该二叉树。

分析:
(1) 由前序确定根节点,中序确定左右子树范围,然后用递归重复这段逻辑。根据前序遍历可知根节点在第一个的位置,根据这个根节点在中序遍历中的位置,左边是左子树,右边是右子树,然后根据中序遍历的左右子树范围判断出前序遍历中的左右子树,按照这个思路将左右子树当作新的遍历递归就可以。例如:前序遍历{1,2,4,7,3,5,6,8},中序遍历{4,7,2,1,5,3,8,6},由前序遍历知根节点是1,所以由中序知左子树序列是{4,7,2},右子树序列是{5,3,8,6},前序中左子树序列的是{2,4,7},右子树序列是{3,5,6,8}。然后将前序序列中的左子树和中序序列的左子树递归,前序序列中的右子树和中序序列的右子树递归。

(2) 跟(1)同样的思路,由后序确定根节点,中序确定左右子树的范围,然后也是使用递归。


理一理代码思路

(1).

/**
 *
 * 输入前序+中序
 *
 * @param first
 * @param center
 * @return
 */
public static TreeNode inputFirstAndCenter(int[] first, int[] center)
{
    if (first == null || center == null || first.length != center.length)
    {
        return null;
    }
    int root_val = first[0];
    TreeNode root = new TreeNode(root_val);

    for (int i = 0; i < center.length; i++)
    {
        if (center[i] == root_val)
        {// 这里要很小心,注意处理好边界判断

            // 当中序数组第一个为根节点时说明这个根节点没有左子树,如果不是就有左子树
            // 前序数组:0是根节点,1~i是左子树,i+1后是右子树
            // 中序数组:i是根节点,0~i-1是左子树,i+1后市右子树
            // 边界情况是:只有根节点,只有左子树,只有右子树
            if (i > 0)
            {
                root.left = inputFirstAndCenter(
                        Arrays.copyOfRange(first, 1, i + 1),
                        Arrays.copyOfRange(center, 0, i));
            }
            if (i < first.length - 1)
            {// 处理边界:中序数组中索引i的值是某一根节点,所以要i+1
                root.right = inputFirstAndCenter(
                        Arrays.copyOfRange(first, i + 1, first.length),
                        Arrays.copyOfRange(center, i + 1, center.length));
            }

            return root;
        }
    }
    // 输入的序列不匹配
    return null;
}

(2).

/**
 * 输入中序和后序
 *
 * @param center
 * @param last
 * @return
 */
public static TreeNode inputCenterAndLast(int[] center, int[] last)
{
    if (last == null || center == null || last.length != center.length)
    {
        return null;
    }
    int root_val = last[last.length - 1];
    TreeNode root = new TreeNode(root_val);

    for (int i = 0; i < center.length; i++)
    {
        if (center[i] == root_val)
        {// 这里要很小心,注意处理好边界判断

            // 后序数组:length-1是根节点,0~i-1是左子树,i~length-2后是右子树
            // 中序数组:i是根节点,0~i-1是左子树,i+1后市右子树
            // 边界情况是:只有根节点,只有左子树,只有右子树
            if (i > 0)
            {
                root.left = inputCenterAndLast(
                        Arrays.copyOfRange(center, 0, i),
                        Arrays.copyOfRange(last, 0, i));
            }
            if (i < center.length - 1 && center.length > 1)
            {
                root.right = inputCenterAndLast(
                        Arrays.copyOfRange(center, i + 1, center.length),
                        Arrays.copyOfRange(last, i, last.length - 1));
            }
            return root;
        }
    }
    // 输入的序列不匹配
    return null;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值