Given preorder and inorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.node
給定一個前序和中序遍歷序列,構建一個二叉樹
注意:
- 二叉樹中元素重複元素算法
前序遍歷第一個元素是根結點(k),在中序遍歷序列中找值爲k的下標idx,idx將中序遍歷序列分紅左右子樹,對前序遍歷序列也同樣,可進行遞歸操做ui
樹結點類spa
public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } }
算法實現類一:.net
public class Solution { public TreeNode buildTree(int[] preorder, int[] inorder) { if (preorder == null || preorder.length ==0){ return null; } HashMap<Integer, Integer> inorderMap = new HashMap<Integer, Integer>(); for (int i=0;i<inorder.length;i++){ inorderMap.put(inorder[i],i); } Deque<TreeNode> stack = new LinkedList<TreeNode>(); TreeNode root = new TreeNode(preorder[0]); stack.push(root); for (int i=1;i<preorder.length;i++){ TreeNode top = stack.peek(); int indexTop = inorderMap.get(top.val); int indexVal = inorderMap.get(preorder[i]); TreeNode node = new TreeNode(preorder[i]); if (indexVal<indexTop){ top.left=node; } else{ while (indexVal>indexTop){ top = stack.pop(); indexTop = stack.isEmpty()?Integer.MAX_VALUE:inorderMap.get(stack.peek().val); } top.right = node; } stack.push(node); } return root; } }
算法實現類二:(會超時)code
public class Solution { public TreeNode buildTree(int[] preorder, int[] inorder) { // 參數校驗 if (preorder == null || inorder == null || preorder.length == 0 || preorder.length != inorder.length) { return null; } return solve(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1); } /** * 構建二叉樹,數據輸入的正確性由輸入數據本身保證 * * @param preorder 先序遍歷的結果 * @param x 先序遍歷的開始位置 * @param y 先序遍歷的結束位置 * @param inorder 中序遍歷的結果 * @param i 中序遍歷的開始位置 * @param j 中序遍歷的結束位置 * @return 二叉樹的根結點 */ public TreeNode solve(int[] preorder, int x, int y, int[] inorder, int i, int j) { if (x >= 0 && x <= y && i >= 0 && i <= j) { // 只有一個元素 if (x == y) { return new TreeNode(preorder[x]); } else if (x < y) { // 記錄根結點的索引 int idx = i; while (idx <= j && inorder[idx] != preorder[x]) { idx++; } // 建立根結點 TreeNode root = new TreeNode(inorder[idx]); // 左子樹的結點個數 int leftLength = idx - i; // if (leftLength > 0) { // x + 1, x + leftLength:左子樹起始和結束位置 root.left = solve(preorder, x + 1, x + leftLength, inorder, i, idx - 1); } // 右子樹的結點個數 int rightLength = j - idx; if (rightLength > 0) { // x + leftLength + 1, y:右子樹起始和結束位置 root.right = solve(preorder, x + leftLength + 1, y, inorder, idx + 1, j); } return root; } } return null; } }