1. 程式人生 > >劍指Offer面試題6 & Leetcode105

劍指Offer面試題6 & Leetcode105

劍指Offer面試題6 & Leetcode105

Construct Binary Tree from Preorder and Inorder Traversal

重建二叉樹

Given preorder and inorder traversal of a tree, construct the binary tree.

解題思路

  考慮:前序遍歷的第一個元素即為根節點的值,然後在中序遍歷中找到該元素,則位於其前的為左子樹的中序遍歷,位於其後的為右子樹的中序遍歷。同理,前序遍歷中第一個元素後先是左子樹的前序遍歷,然後是右子樹的前序遍歷。根據這個特點,用遞迴的方法實現二叉樹的重建。

  注意這道題,如果想減小執行時間,在遞迴過程中儘量傳遞原陣列中各子樹遍歷的序號,而不是構建新的陣列進行傳遞。下面兩種解法,一種為傳遞陣列,一種為傳遞序號,均AC但時間不同。

Solution1 時間較長

public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder.length == 0 && inorder.length == 0) 
            return null;
        TreeNode root = new TreeNode(preorder[0
]); int flag = -1; for(int i=0;i<inorder.length;i++){ if(inorder[i] == root.val){ flag = i; break; } } int[] newInorderLeft = new int[flag]; int[] newPreorderLeft = new int[flag]; int[] newInorderRight = new
int[inorder.length-flag-1]; int[] newPreorderRight = new int[preorder.length-flag-1]; for(int i=0;i<flag;i++){ newInorderLeft[i] = inorder[i]; } for(int i=0;i<flag;i++){ newPreorderLeft[i] = preorder[i+1]; } for(int i=0;i<inorder.length-flag-1;i++){ newInorderRight[i] = inorder[flag+1+i]; } for(int i=0;i<inorder.length-flag-1;i++){ newPreorderRight[i] = preorder[flag+1+i]; } root.left = buildTree(newPreorderLeft,newInorderLeft); root.right = buildTree(newPreorderRight, newInorderRight); return root; }

Solution2 時間較短

public TreeNode buildTree(int[] preorder, int[] inorder) {
        if (preorder.length == 0 && inorder.length == 0)
            return null;
        return helper(0, 0, inorder.length - 1, preorder, inorder);
    }

public TreeNode helper(int preStart, int inStart, 
    int inEnd, int[] preorder, int[] inorder) {
        if (preStart >= preorder.length || inStart > inEnd)
            return null;
        TreeNode root = new TreeNode(preorder[preStart]);
        int flag = -1;
        for (int i = inStart; i <= inEnd; i++) {
            if (inorder[i] == root.val) {
                flag = i;
                break;
            }
        }
        root.left = helper(preStart + 1, inStart, flag - 1, preorder, inorder);
        //注意對於右子樹的前序遍歷,開始的序號要減去其中序遍歷開始的序號,防止溢位, 即 flag + 1 - inStart 為右子樹針對此時的根節點的位移量。
        root.right = helper(preStart + flag + 1 - inStart, flag + 1, inEnd, preorder, inorder);
        return root;
    }