二叉树 给定先序遍历结果和中序遍历结果求后序遍历结果

294 阅读2分钟

题目

给定一组二叉树先序遍历结果和中序遍历结果,求二叉树的后序遍历结果

  • 首先根据先序遍历的首元素能够确定后序遍历的尾元素,此时已经搞定后序遍历最后一个结果了,对于剩下的部分,按照左右子树划分区间
  • 如下图,根据中序中先序首字母的位置,能够找到左右子树的区间,同理,中序中的左右子树规模,找到先序中左右子树的规模
  • 根据前面得到的左右子树规模,去设置后序的左右子树规模,然后根据每个子树中先序遍历的首元素能够确定后序遍历的尾元素来填充后序结果,整个填充过程根据划分的左右子树递归进行

image.png

function process(pre, mid) {
  let post = [],
    N = pre.length;

  set(pre, mid, post, 0, N - 1, 0, N - 1, 0, N - 1);

  function set(pre, mid, post, prei, prej, midi, midj, posti, postj) {
    // 越界退出
    if (prei > prej) {
      return;
    }
    if (prei === prej) {
      // 区间只剩1个数,不需要再分了,直接填
      post[posti] = pre[prej];
      return;
    }
    // 后序最后一个填先序第一个
    post[postj] = pre[prei];

    let find = midi;

    // 在中序中找到先序第一个的位置
    for (; find <= midj; find++) {
      if (mid[find] == pre[prei]) {
        break;
      }
    }
    // 构造左树部分

    set(
      pre,
      mid, 
      post,
      prei + 1, // 先序左子树左边界
      prei + find - midi, // 先序左子树右边界, find-midi 为左树规模
      midi, // 中序左子树左边界
      find - 1,// 中序左子树右边界
      posti,// 后序左子树左边界
      posti + find - midi // 后序左子树右边界
    );
    // 构造右树部分
    set(
      pre,
      mid,
      post,
      prei + find - midi + 1, // 先序右子树左边界
      prej,// 先序右子树右边界
      find + 1, // 中序右子树左边界
      midj, // 中序右子树右边界
      posti + find - midi, // 后序右子树左边界
      postj - 1 // 后序右子树右边界
    );
  }
}