日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[剑指offer][JAVA]面试题第[07]题[重建二叉树][递归]

發布時間:2023/12/10 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [剑指offer][JAVA]面试题第[07]题[重建二叉树][递归] 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【問題描述】[中等]

輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重復的數字。例如,給出前序遍歷 preorder = [3,9,20,15,7] 中序遍歷 inorder = [9,3,15,20,7] 返回如下的二叉樹:3/ \9 20/ \15 7

【解答思路】

1. 遞歸解釋1

關鍵要理解
前序遍歷的左右子樹根節點 可以根據中序遍歷得到的左右子樹的長度推斷

時間復雜度:O(N) 空間復雜度:O(N)

import java.util.HashMap; import java.util.Map;class TreeNode {int val;TreeNode left;TreeNode right;TreeNode(int x) {val = x;} }public class Solution {// 使用全局變量是為了讓遞歸方法少傳一些參數,不一定非要這么做private Map<Integer, Integer> reverses;private int[] preorder;public TreeNode buildTree(int[] preorder, int[] inorder) {int preLen = preorder.length;int inLen = inorder.length;// 可以不做判斷,因為題目中給出的數據都是有效的if (preLen != inLen) {return null;}this.preorder = preorder;// 以空間換時間,否則,找根結點在中序遍歷中的位置需要遍歷reverses = new HashMap<>(inLen);for (int i = 0; i < inLen; i++) {reverses.put(inorder[i], i);}return buildTree(0, preLen - 1, 0, inLen - 1);}/*** 根據前序遍歷數組的 [preL, preR] 和 中序遍歷數組的 [inL, inR] 重新組建二叉樹** @param preL 前序遍歷數組的區間左端點* @param preR 前序遍歷數組的區間右端點* @param inL 中序遍歷數組的區間左端點* @param inR 中序遍歷數組的區間右端點* @return 構建的新二叉樹的根結點*/private TreeNode buildTree(int preL, int preR,int inL, int inR) {if (preL > preR || inL > inR) {return null;}// 構建的新二叉樹的根結點一定是前序遍歷數組的第 1 個元素int pivot = preorder[preL];TreeNode root = new TreeNode(pivot);int pivotIndex = reverses.get(pivot);// 這一步得畫草稿,計算邊界的取值,必要時需要解方程,并不難root.left = buildTree(preL + 1, preL + (pivotIndex - inL), inL, pivotIndex - 1);root.right = buildTree(preL + (pivotIndex - inL) + 1, preR, pivotIndex + 1, inR);return root;} }
2. 遞歸解釋2


時間復雜度:O(N) 空間復雜度:O(N)

//利用原理,先序遍歷的第一個節點就是根。在中序遍歷中通過根 區分哪些是左子樹的,哪些是右子樹的//左右子樹,遞歸HashMap<Integer, Integer> map = new HashMap<>();//標記中序遍歷int[] preorder;//保留的先序遍歷public TreeNode buildTree(int[] preorder, int[] inorder) {this.preorder = preorder;for (int i = 0; i < preorder.length; i++) {map.put(inorder[i], i);}return recursive(0,0,inorder.length-1);}/*** @param pre_root_idx 先序遍歷的索引* @param in_left_idx 中序遍歷的索引* @param in_right_idx 中序遍歷的索引*/public TreeNode recursive(int pre_root_idx, int in_left_idx, int in_right_idx) {//相等就是自己if (in_left_idx > in_right_idx) {return null;}//root_idx是在先序里面的TreeNode root = new TreeNode(preorder[pre_root_idx]);// 有了先序的,再根據先序的,在中序中獲 當前根的索引int idx = map.get(preorder[pre_root_idx]);//左子樹的根節點就是 左子樹的(前序遍歷)第一個,就是+1,左邊邊界就是left,右邊邊界是中間區分的idx-1root.left = recursive(pre_root_idx + 1, in_left_idx, idx - 1);//由根節點在中序遍歷的idx 區分成2段,idx 就是根//右子樹的根,就是右子樹(前序遍歷)的第一個,就是當前根節點 加上左子樹的數量// pre_root_idx 當前的根 左子樹的長度 = 左子樹的左邊-右邊 (idx-1 - in_left_idx +1) 。最后+1就是右子樹的根了root.right = recursive(pre_root_idx + (idx-1 - in_left_idx +1) + 1, idx + 1, in_right_idx);return root;}

【總結】

1.前中后序遍歷變化的是[中]的位置,左到右的順序不改變
  • 前序遍歷 中左右
  • 中序遍歷 左中右
  • 后續遍歷 左右中
2.前序+中序遍歷可畫出原二叉樹
3. 多畫圖 寫寫寫 遍歷代碼 手撕變量 大腦保持清醒

轉載鏈接:https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/solution/mian-shi-ti-07-zhong-jian-er-cha-shu-di-gui-fa-qin/
來源:力扣(LeetCode)
轉載鏈接:https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/solution/er-cha-shu-de-qian-xu-bian-li-fen-zhi-si-xiang-by-/
來源:力扣(LeetCode)

總結

以上是生活随笔為你收集整理的[剑指offer][JAVA]面试题第[07]题[重建二叉树][递归]的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。