1. 程式人生 > 其它 >LeetCode-劍指offer-07-重建二叉樹

LeetCode-劍指offer-07-重建二叉樹

技術標籤:LeetCode劍指offer刷題記錄二叉樹遞迴

目錄


題目要求

原題連結劍指 Offer 07. 重建二叉樹 | 105. 從前序與中序遍歷序列構造二叉樹

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

例如,給出

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

返回如下的二叉樹:

    3
   / \
  9  20
    /  \
   15   7

限制:

0 <= 節點個數 <= 5000


解題過程

詳情見本人的lc題解

簡單理解-遞迴重建二叉樹

遞迴 | 時間複雜度: O ( n ) O(n) O(n) | 空間複雜度: O ( n ) O(n) O(n) | 推薦

時間複雜度:HashMap的遍歷儲存需要 O ( n ) O(n) O(n),遞迴共建立了n個節點,每次遞迴佔用 O ( 1 ) O(1) O(1)的節點建立開銷損耗

空間複雜度:HashMap佔 O ( n ) O(n) O(n),最差情況,樹退化為連結串列,佔用 O ( n ) O(n) O(n)的深度,最好的情況為滿二叉樹,深度為 o ( l o g n ) o(logn) o(logn)

image-20210205133458565

class Solution {
    int
[] preorder; HashMap<Integer, Integer> map = new HashMap<>(); // 前序遍歷 preorder: 根 -- 左 -- 右 第一個肯定是根節點 // 中序遍歷 inorder: 左 -- 根 -- 右 public TreeNode buildTree(int[] preorder, int[] inorder) { this.preorder = preorder; for(int i = 0; i < inorder.length; i++){
map.put(inorder[i], i); } return rebuild(0, 0, inorder.length - 1); } // pre_root_index : 根節點 在 前序遍歷中的下標 // in_left_index: 該節點在中序遍歷中的左邊界 // in_right_index: 該節點在中序遍歷中的右邊界 public TreeNode rebuild(int pre_root_index, int in_left_index, int in_right_index){ if(in_left_index > in_right_index) return null; // 根節點在中序遍歷中的位置:in_root_index int in_root_index = map.get(preorder[pre_root_index]); // 建立一個根節點 TreeNode node = new TreeNode(preorder[pre_root_index]); // 尋找node的左節點: // 在前序遍歷中的位置就是 根節點的下標 + 1(右邊一個單位) // 在中序遍歷中的位置就是: 1. 左邊界不變(因為無法確定),2. 右邊界就是根節點的左邊一個單位 in_root_index - 1 node.left = rebuild(pre_root_index + 1, in_left_index, in_root_index - 1); // 尋找node的右節點: // 在前序遍歷中的位置就是 根節點的下標 + 左子樹長度 + 1 // 在中序遍歷中的位置就是: 1. 左邊界在根節點的右邊一個單位 in_root_index + 1, 2. 右邊界無法確定 node.right = rebuild(pre_root_index + in_root_index - in_left_index + 1, in_root_index + 1, in_right_index); return node; } }