给出先序后序遍历求中序遍历&&编程细节及重要结论

题目

链接: https://ac.nowcoder.com/acm/contest/19859/O
题意:
 给定一棵有n个结点的二叉树的先序遍历与后序遍历序列,求其中序遍历序列。若某节点只有一个子结点,则此处将其看作左儿子结点


输入

5,[3,2,1,4,5],[1,5,4,2,3]

输出

[1,2,5,4,3]

注意:输出的是一个int类型的数组
#解析 : 
先说明一下题目给的条件:cond“若某节点只有一个子结点,则此处将其看作左儿子结点”。例子给出的二叉树图,3节点只有一个左子树,但实际上可以把左子树放到3节点的右边(变成右子树),先序后序遍历仍然和题目给出的一样。


这里说下为什么会这样:根据先序和后序遍历的特点,如果一个节点只有左子树(或只有右子树),先序都为 rt ls (rt rs),后序都为 ls rt (rs rt)。只有右子树先序后序遍历也一样。(rt父节点,左右子树ls rt)。例如题目中的节点5可以接在4节点的左边也可以接在右边。你可以发现先序都是45,后序都是54。


二叉树的形态分析:如果没有条件cond,二叉树的形态会有2^k种(k为树中所有 只有一个子结点的 结点的数目),例子中,k=2,共4种形态,3节点的左子树可接到右边,4节点的左子树也可以接到右边。



  综上,我们可以得出一个结论,有右子树一定会有左子树。所以编程的时候我们以左子树为主(一直满足pre[l1++]==suf[r2--]条件,说明只有左子树,一直递归左子树,右子树null),当pre[l1]!=suf[r2]时,说明有右子树了。假如cnt为多余的部分,即cnt(suf[k],suf[r2]],suf[k]==pre[l1],向左递归,然后将多余的部分递归右子树即可。

并且我们可以发现suf[r2]==pre[r1-cnt],这就为我们每次递归一次,只要不l1>r1||l2>r2,我们都建树(递归的每个状态都满足pre[l1]==suf[r2],每次进去都建一个节点),判断下一次,如果相等递归左子树,不相等,找到cnt,向两边递归(不相等说明有右子树)


AC代码 - - -

#solution1

import java.util.*;
class Node{
    int v;
    Node ls,rs;
    public Node() {
        v = -1;
        ls = null;
        rs = null;
    }
    public Node(int v,Node ls,Node rs) {
        this.v = v;
        this.ls = ls;
        this.rs = rs;
    }
}
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 
     * @param n int 二叉树节点数量
     * @param pre int一维数组 前序序列
     * @param suf int一维数组 后序序列
     * @return int一维数组
     */
    static int a[],cnt = 0;
    static Node build(int l1,int r1,int l2,int r2,int[] pre,int[] suf) {
        if(l1>r1||l2>r2) return null;
        Node nd = new Node();
        nd.v = pre[l1];
        int cnt = 0, p = r2;
        while(--p>=l2&&l1+1<=r1) {
            if(pre[l1+1]==suf[p]) {
                break;
            }else {
                cnt++;
            }
        }
        nd.ls = build(l1+1,r1-cnt,l2,r2-cnt-1,pre,suf);
        nd.rs = cnt==0?null:build(r1-cnt+1,r1,r2-cnt,r2-1,pre,suf);
        return nd;
    }
    static void inorder(Node nd) {
        if(nd==null) return ;
        inorder(nd.ls);
        a[cnt++] = nd.v;
        inorder(nd.rs);
    }
    public int[] solve (int n, int[] pre, int[] suf) {
        Node nd = build(0,n-1,0,n-1,pre,suf);
        a = new int[n];
        inorder(nd);
        return a;
    }
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值