LeetCode刷题笔记 105&106.从遍历序列构造二叉树 *

总结

在二叉树任一节点都可以看成 根,左子树,右子树 三个部分,不管什么遍历方法,这三部分在遍历数组中的长度都是一样长的(这不是废话吗?)。
所以 分治 + 递归 就可以“轻松”的解决了。

代码实现上大概有三种方法:

  1. 递归传递 边界,长度
  2. 递归传递 两个新的数组
  3. 用map来记录坐标信息

105.从前序与后序遍历序列构造二叉树

总结
在这里插入图片描述

Sample & Demo Code
class Solution {
    int[] preorder;
    int[] inorder;
    int pre_idx = 0;
    HashMap<Integer, Integer> idx_map = new HashMap<>();
    
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        this.preorder = preorder;
        this.inorder = inorder;
        
        int idx = 0;
        for(int i : inorder)
            idx_map.put(i, idx++);
        
        return helper(0, idx);
    }
    
    private TreeNode helper(int left, int right) {
        if(left >= right) return null;
        
        int root_val = preorder[pre_idx];
        TreeNode root = new TreeNode(root_val);
        int index = idx_map.get(root_val);
        
        pre_idx++;
        root.left = helper(left, index);
        root.right = helper(index+1, right);
        
        return root;
    }
      
}
Sample Code
class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return build(preorder, inorder, 0, 0, inorder.length);
    }

    public TreeNode build(int[] preOrder, int[] inOrder, int preStart, int inStart, int length) {
        if (length==0) return null;
        int root_val = preOrder[preStart];
        TreeNode treeNode = new TreeNode(root_val);
        if (length== 1) return treeNode;
        
        //必须从后开始遍历,不然会非常慢
        for (int i = length-1; i >= 0; i--) {
            if (root_val == inOrder[inStart+i]) {
                treeNode.left = build(preOrder, inOrder, preStart+1, inStart, i);
                treeNode.right = build(preOrder, inOrder,  preStart+1+i, inStart+i+1, length-i-1);
                return treeNode;
            }
        }
        return null;
    }
}

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

总结
在这里插入图片描述

Sample & Demo Code
public class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        int inlen = inorder.length;
        int polen = postorder.length;
        
        if(inorder.length == 0) return null;
        if(inorder.length == 1) return new TreeNode(inorder[0]);
        
        int root_val = postorder[polen-1];
        int point = 0;
        for(int i = 0; i < inlen; i++) {
            if(inorder[i] == root_val) {
                point = i;
                break;
            }
        }
        
        TreeNode root = new TreeNode(root_val);
        root.left = buildTree(Arrays.copyOfRange(inorder, 0, point), Arrays.copyOfRange(postorder, 0, point));
        root.right = buildTree(Arrays.copyOfRange(inorder, point+1, inlen), Arrays.copyOfRange(postorder, point, polen-1));
        return root;
    }
}
Sample Code

在这里插入图片描述
在root.right = buildeTree(…);处的stop的值其实是中序表的同一层次的根节点
即如图为例,第一层递归是3,进入root的右子树的递归后,变成了20
同时需要注意,这种写法每次都会递归到叶子节点的两个null子节点后才会触发return条件
这种写法在写递归的root.left = … 和 root.right = … 的时候顺序不能颠倒,而其他方法在这里是可以颠倒的,因为这种写法公用了 in 和 post,并依赖于 in 和 post

class Solution {
    private int in;
    private int post;

    public TreeNode buildTree(int[] inorder, int[] postorder) {
        int n = inorder.length;
        in = n - 1;
        post = n - 1;
        return buildTree(inorder, postorder, (long) Integer.MIN_VALUE - 1);
    }

    private TreeNode buildTree(int[] inorder, int[] postorder, long stop) {
        System.out.println("stop:"+stop+", in:"+in+", post:"+post);
        if (post < 0) return null;
            
        if (inorder[in] == stop) {
            in--;
            return null;
        }
        int rootVal = postorder[post--];
        TreeNode root = new TreeNode(rootVal);
        
        root.right = buildTree(inorder, postorder, rootVal);
        root.left = buildTree(inorder, postorder, stop);

        return root;
    }
}

>Input:
[9,3,15,20,7]
[9,15,7,20,3]
>Ouput:
in:4, post:4, stop:-2147483649
in:4, post:3, stop:3
in:4, post:2, stop:20
in:4, post:1, stop:7
in:3, post:1, stop:20
in:2, post:1, stop:3
in:2, post:0, stop:15
in:1, post:0, stop:3
in:0, post:0, stop:-2147483649
in:0, post:-1, stop:9
in:0, post:-1, stop:-2147483649
Sample Code
public class Solution {
    private int[] postorder;
    private Map<Integer, Integer> hash;

    public TreeNode buildTree(int[] inorder, int[] postorder) {
        int inLen = inorder.length;
        int postLen = postorder.length;

        this.postorder = postorder;
        hash = new HashMap<>();
        for (int i = 0; i < inLen; i++) {
            hash.put(inorder[i], i);
        }

        return buildTree(0, inLen - 1, 0, postLen - 1);
    }

    private TreeNode buildTree(int inLeft, int inRight, int postLeft, int postRight) {
        if (inLeft > inRight || postLeft > postRight)
            return null;

        int pivot = postorder[postRight];
        int pivotIndex = hash.get(pivot);
        TreeNode root = new TreeNode(pivot);
        root.right = buildTree(pivotIndex + 1, inRight, postRight - inRight + pivotIndex, postRight - 1);
        root.left = buildTree(inLeft, pivotIndex - 1, postLeft, postRight - inRight + pivotIndex - 1);
        
        return root;
    }
}

链接:
https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/solution/hou-xu-bian-li-python-dai-ma-java-dai-ma-by-liwe-2/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值