Leetcode105. 從前序與中序遍歷序列構造二叉樹
阿新 • • 發佈:2021-09-28
Leetcode105. 從前序與中序遍歷序列構造二叉樹
題目描述
/**
* 給定一棵樹的前序遍歷 preorder 與中序遍歷 inorder。
* <p>
* 請構造二叉樹並返回其根節點。
*/
思路分析
- 已知前序遍歷和中序遍歷的陣列,構造其二叉樹
- 根據前序遍歷和中序遍歷的特點可知,前序遍歷在遍歷二叉樹時先遍歷根節點,隨後遍歷左子樹,最後遍歷右子樹,中序遍歷在遍歷二叉樹時先遍歷左子樹,隨後遍歷根節點,最後遍歷右子樹
- 可知前序遍歷時始終先遍歷根節點,因此前序遍歷的第一個節點就是二叉樹的根節點
- 由中序遍歷的特點可知根節點始終位於最中間,對中序遍歷的陣列進行hash對映,鍵為節點值,值為對中序遍歷陣列的索引,因此可以根據鍵很快找到其位置
- 確立樹的根節點後,使用遞迴的思路,構造左子樹和右子樹,即將中序遍歷陣列從根節點一分為二進行構造
- 原始碼及詳解見下
原始碼及分析
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; }