leetCode_105ツリーの前順および中次トラバーサルに基づいてバイナリツリーを構築します

トピック:

二分木は、木の前順および中次トラバーサルに従って構築されます。

注:
ツリーに重複する要素はないと想定できます。

たとえば、

Preorder traversal preorder = [3,9,20,15,7] Inorder
traversal inorder = [9,3,15,20,7]
は、次のバイナリツリーを返します。

    3
   / \
  9 20
    / \
   15 7

分析方法:分割統治

「プレオーダートラバーサル」と「ミドルオーダートラバーサル」の定義を組み合わせる

プリオーダートラバーサルの最初のノードは、バイナリツリーのルートノードでなければなりません。

インオーダートラバーサルのルートノードは、インオーダートラバーサルを2つの部分に分割します。左側の部分はバイナリツリーのルートノードの左側のサブツリーを構成し、右側の部分はバイナリツリーのルートノードの右側のサブツリーを構成します。

ルートノードとして3を決定します。順序トラバーサルによれば、3は左側のルートノードの左側のサブツリーであり、右側のルートノードの右側のサブツリーであることがわかります。次に、再帰...

次に、アイデアを繰り返します

preLeftが前順トラバーサルの左境界であり、preRightが前順序トラバーサルの右境界であり、inLeftが中順序トラバーサルの左境界であり、inRightが中順序トラバーサルの右境界であるとします。

次に、preLeftはルートノードルートを指し、ルートノードの左側のサブツリーの左側の境界はpreLeft + 1です。同時に、ルートノードは中位のトラバーサルで見つけることができます。pIndexを中位のトラバースルートノードを指すように設定し、中位の順序がミドルルートノードの左の子をトラバースします。ツリーの間隔は[inLeft、pIndex-1]で、右側のサブツリーの間隔は[pIndex + 1、inRight]です。残っているのは、プリオーダが左サブツリーの右境界と右サブツリーの左境界をトラバースすることですが、左サブツリーの長さは、次の関係によって取得できる中次トラバースの長さと同じです。

最終的な結果は次のとおりです

コードを書く:

    public static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode(int x) {
            val = x;
        }

    }


    public static TreeNode buildTree(int[] preorder, int[] inorder) {
        int preLen = preorder.length;//前序遍历的长度
        int inLen = inorder.length;//中序遍历的长度

        // 可以不做判断,因为题目中给出的数据都是有效的
        if (preLen != inLen) {
            return null;
        }

        // 以空间换时间,否则,找根结点在中序遍历中的位置需要遍历
        Map<Integer, Integer> map = new HashMap<>(inLen);
        for (int i = 0; i < inLen; i++) {
            map.put(inorder[i], i);
        }

        return buildTree(preorder,0, preLen - 1,map, 0, inLen - 1);
    }

    /**
     * 根据前序遍历数组的 [preL, preR] 和 中序遍历数组的 [inL, inR] 重新组建二叉树
     *
     *
     * @param preorder
     * @param preL 前序遍历数组的区间左端点
     * @param preR 前序遍历数组的区间右端点
     * @param map
     * @param inL  中序遍历数组的区间左端点
     * @param inR  中序遍历数组的区间右端点
     * @return 构建的新二叉树的根结点
     */
    private static TreeNode buildTree(int[] preorder, int preL, int preR,
                                      Map<Integer, Integer> map, int inL, int inR) {
        if (preL > preR || inL > inR) {
            return null;
        }
        // 构建的新二叉树的根结点一定是前序遍历数组的第 1 个元素
        int rootVal = preorder[preL];
        TreeNode root = new TreeNode(rootVal);

        int pIndex = map.get(rootVal );//中序遍历根节点的索引

        // 按照图中描述,计算边界的取值
        root.left = buildTree(preorder, preL + 1, preL + (pIndex - inL), map, inL, pIndex - 1);
        root.right = buildTree(preorder, preL + (pIndex - inL) + 1, preR, map, pIndex + 1, inR);
        return root;
    }

これで終わりです!

 

ソース:LeetCode
リンク:https ://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal
著作権はLeetCode が所有しています商用転載については、正式な許可書にご連絡ください。非商用転載については、出典を明記してください。

おすすめ

転載: blog.csdn.net/weixin_43419256/article/details/107832473