1. 程式人生 > 其它 >Leetcode105. 從前序與中序遍歷序列構造二叉樹

Leetcode105. 從前序與中序遍歷序列構造二叉樹

Leetcode105. 從前序與中序遍歷序列構造二叉樹

題目描述

/**
     * 給定一棵樹的前序遍歷 preorder 與中序遍歷  inorder。
     * <p>
     * 請構造二叉樹並返回其根節點。
     */

思路分析

  1. 已知前序遍歷和中序遍歷的陣列,構造其二叉樹
  2. 根據前序遍歷和中序遍歷的特點可知,前序遍歷在遍歷二叉樹時先遍歷根節點,隨後遍歷左子樹,最後遍歷右子樹,中序遍歷在遍歷二叉樹時先遍歷左子樹,隨後遍歷根節點,最後遍歷右子樹
  3. 可知前序遍歷時始終先遍歷根節點,因此前序遍歷的第一個節點就是二叉樹的根節點
  4. 由中序遍歷的特點可知根節點始終位於最中間,對中序遍歷的陣列進行hash對映,鍵為節點值,值為對中序遍歷陣列的索引,因此可以根據鍵很快找到其位置
  5. 確立樹的根節點後,使用遞迴的思路,構造左子樹和右子樹,即將中序遍歷陣列從根節點一分為二進行構造
  6. 原始碼及詳解見下

原始碼及分析

private Map<Integer, Integer> map;

    /**
     * 
     * @param preorder 前序遍歷陣列
     * @param inorder 中序遍歷陣列
     * @return
     */
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        int n = inorder.length;
        //構造雜湊對映,快速定位根節點
        map = new HashMap<>();
        for (int i = 0; i < n; i++) {
            map.put(inorder[i], i);
        }
        return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);

    }

    /**
     *
     * @param preorder 前序遍歷陣列
     * @param inorder 中序遍歷陣列
     * @param preorder_left 前序遍歷左側節點索引
     * @param preorder_right 前序遍歷右側節點索引
     * @param inorder_left 中序遍歷左側節點索引
     * @param inorder_right 中序遍歷右側節點索引
     * @return
     */
    public TreeNode myBuildTree(int[] preorder, int[] inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {
        //遞迴結束條件
        if (preorder_left > preorder_right) {
            return null;
        }
        //前序遍歷的第一個節點就是根節點
        int preorder_root = preorder_left;
        //在中序遍歷中定位根節點
        int inorder_root = map.get(preorder[preorder_root]);

        //先把根節點建立出來
        TreeNode root = new TreeNode(preorder[preorder_root]);
        //得到左子樹中的節點數目
        int size_left_subtree = inorder_root - inorder_left;
        //遞迴的構造左子樹,並連線到根節點
        root.left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1);
        //遞迴的構造右子樹,並連線到根節點
        root.right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);
        return root;
    }