1. 程式人生 > 其它 >劍指 Offer 07. 重建二叉樹(中等)

劍指 Offer 07. 重建二叉樹(中等)

技術標籤:LeetCodeleetcode二叉樹

劍指 Offer 07. 重建二叉樹

輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。

例如,給出

前序遍歷 preorder =[3,9,20,15,7]
中序遍歷 inorder = [9,3,15,20,7]

返回如下的二叉樹:

    3
   / \
  9  20
    /  \
   15   7

限制:

0 <= 節點個數 <= 5000

我的Java程式碼:

思路:給的函式介面直接拿來遞迴感覺還需要再新建陣列,比較麻煩,所以用另一個方法來實現遞迴建樹。遞迴方法中通過移動兩對指標分別界定子樹在兩個陣列中的位置。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
   public TreeNode buildTree(int[] preorder, int[] inorder) {
		 return build(preorder,0,preorder.length,inorder,0,inorder.length);
	 }
	 public TreeNode build(int[] preorder, int preorderLow, int preorderHigh, 
			 int[] inorder, int inorderLow, int inorderHigh) {	
		 if(preorderLow > preorderHigh || inorderLow > inorderHigh || preorderLow == preorder.length) {
			 return null;
		 }

		 int key = preorder[preorderLow];
		 int k = inorderLow,left;
		 for(int i = inorderLow;i < inorderHigh;i++) {
			 if(key == inorder[i]) {
				 k = i;
				 break;
			 }
		 }
		 left = k - inorderLow;
		 
		 TreeNode t = new TreeNode(key);
		 t.left = build(preorder,preorderLow+1,preorderLow+left,inorder,inorderLow,k);
		 t.right = build(preorder,preorderLow+left+1,preorderHigh,inorder,k+1,inorderHigh);
		 return t;
	 }
}

學習別人的程式碼:

作者:LeetCode-Solution
連結:https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/solution/mian-shi-ti-07-zhong-jian-er-cha-shu-by-leetcode-s/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

思路:迭代

可以使用棧儲存遍歷過的節點。初始時令中序遍歷的指標指向第一個元素,遍歷前序遍歷的陣列,如果前序遍歷的元素不等於中序遍歷的指標指向的元素,則前序遍歷的元素為上一個節點的左子節點。如果前序遍歷的元素等於中序遍歷的指標指向的元素,則正向遍歷中序遍歷的元素同時反向遍歷前序遍歷的元素,找到最後一次相等的元素,將前序遍歷的下一個節點作為最後一次相等的元素的右子節點。其中,反向遍歷前序遍歷的元素可通過棧的彈出元素實現。

  • 使用前序遍歷的第一個元素建立根節點。
  • 建立一個棧,將根節點壓入棧內。
  • 初始化中序遍歷下標為 0。
  • 遍歷前序遍歷的每個元素,判斷其上一個元素(即棧頂元素)是否等於中序遍歷下標指向的元素。
    • 若上一個元素不等於中序遍歷下標指向的元素,則將當前元素作為其上一個元素的左子節點,並將當前元素壓入棧內。
    • 若上一個元素等於中序遍歷下標指向的元素,則從棧內彈出一個元素,同時令中序遍歷下標指向下一個元素,之後繼續判斷棧頂元素是否等於中序遍歷下標指向的元素,若相等則重複該操作,直至棧為空或者元素不相等。然後令當前元素為最後一個想等元素的右節點。
  • 遍歷結束,返回根節點。

精選第一的題解更好理解迭代方法:詳細通俗的思路分析,多解法

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if (preorder == null || preorder.length == 0) {
            return null;
        }
        TreeNode root = new TreeNode(preorder[0]);
        int length = preorder.length;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(root);
        int inorderIndex = 0;
        for (int i = 1; i < length; i++) {
            int preorderVal = preorder[i];
            TreeNode node = stack.peek();
            if (node.val != inorder[inorderIndex]) {
                node.left = new TreeNode(preorderVal);
                stack.push(node.left);
            } else {
                while (!stack.isEmpty() && stack.peek().val == inorder[inorderIndex]) {
                    node = stack.pop();
                    inorderIndex++;
                }
                node.right = new TreeNode(preorderVal);
                stack.push(node.right);
            }
        }
        return root;
    }
}

作者:LeetCode-Solution
連結:https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/solution/mian-shi-ti-07-zhong-jian-er-cha-shu-by-leetcode-s/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。