成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

LeetCode題解之重建二叉樹

開發 前端
今天繼續二叉樹相關的算法題,輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重復的數字。

[[388826]]

前言

今天繼續二叉樹相關的算法題

題目

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

例如,給出

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

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

返回如下的二叉樹:

  1.  3 
  2.  / \ 
  3. 9  20 
  4.   /  \ 
  5.  15   7 

題解

上周說過 前序遍歷和后序遍歷,其實這種前序、中序、后序都是相對于中間節點的處理順序。

比如先序遍歷的順序就應該是:

[ 根節點 | 左子樹 | 右子樹 ]

同理,中序遍歷的順序就是:

[ 左子樹 | 根節點 | 右子樹 ]

所以前序遍歷的第一個元素肯定就是 根節點。

然后,我們就能在 中序遍歷找到根節點,并正確把中序遍歷區分為三部分,也就是左子樹中序、根節點、右子樹中序。

舉個例子:

如果只有三個元素,那么到這里就能結束了,因為樹已經能畫出來了。

比如前序是【3,9,20】,中序是【9,3,20】

我們根據中序知道了根節點3,然后在中序中就能區分出左子樹節點9,根節點3,右子樹節點20。

現在我們擴散開,如果不止3個節點呢?

舉例2:

如果是5個元素,比如前序是[3,9,20,15,7],中序是[9,3,15,20,7]

經過第一次分割,我們把中序分成了左子樹9,根節點3,右子樹【15,20,7】

這時候,右子樹該怎么分呢?跟節點是什么呢?又不知道了。

所以這時候要再聯系到前序遍歷,根據我們所知道的左子樹節點,得出前序中右子樹應該為【20,15,7】,所以右子樹的根節點為20。

總之,就是前序和中序互相幫助,最終通過遞歸完成我們樹的構建。

解法1

解法1就是依靠遞歸。

遞歸的過程就是找出每個父節點的左子樹節點和右子樹節點,一共三個值。

而最終的取值都是從前序列表中取值,其實就是取每個小樹的父節點。

而中序遍歷數組的作用就是找到 每次父節點在中序遍歷數組中的位置。

得出如下算法。

  1. /** 
  2.  * Definition for a binary tree node. 
  3.  * public class TreeNode { 
  4.  *     int val; 
  5.  *     TreeNode left
  6.  *     TreeNode right
  7.  *     TreeNode(int x) { val = x; } 
  8.  * } 
  9.  */ 
  10. class Solution { 
  11.     int[] preorder; 
  12.     HashMap<IntegerInteger> dic = new HashMap<>(); 
  13.     public TreeNode buildTree(int[] preorder, int[] inorder) { 
  14.         this.preorder = preorder; 
  15.         for(int i = 0; i < inorder.length; i++) 
  16.             dic.put(inorder[i], i); 
  17.         return recur(0, 0, inorder.length - 1); 
  18.     } 
  19.     TreeNode recur(int root, int leftint right) { 
  20.         if(left > rightreturn null;         
  21.         //根節點                   
  22.         TreeNode node = new TreeNode(preorder[root]);    
  23.         //分割點     
  24.         int i = dic.get(preorder[root]);         
  25.         node.left = recur(root + 1, left, i - 1);  
  26.         node.right = recur(root + i - left + 1, i + 1, right);  
  27.         return node;       
  28.     } 

其中每次取右子樹的根節點需要注意:

左子樹的節點數為i-left。

所以在前序遍歷數組中,左子樹的節點+根節點位置,就是左子樹的最后一個節點位置,也就是root+i-left。

最后得出右子樹的根節點為:root + i - left + 1

而遞歸的結束條件就是,左右子樹節點相遇,也就是left>right。

時間復雜度

O(n),n為樹的節點數量。

空間復雜度

O(N),用到了HashMap。

解法2

還有一種辦法叫做迭代方法,這個方法挺巧妙的,當時也是看了很久的官方解答才想明白的,哈哈。

它的主要思想是理解前序遍歷和中序遍歷的規則,然后一個個從前序遍歷中取值,并放到合適的位置。

比如以下這個二叉樹:

  1.         3 
  2.        / \ 
  3.       9  20 
  4.      /  /  \ 
  5.     8  15   7 
  6.    / \ 
  7.   5  10 
  8.  / 

前序遍歷,可以發現是首先把最左邊的節點列出來,也就是 3,9,8,5,4

而中序列表是反著來的,從最左邊的下面開始,往上列,如果發現某個節點有右子節點,就開始往右邊列。

比如 4,5,8。這時候發現8有右子節點,那么就開始數 10 ,然后繼續最左邊往上,9,3。

最后列一下完整的前序和中序:

preorder = [3, 9, 8, 5, 4, 10, 20, 15, 7] inorder = [4, 5, 8, 10, 9, 3, 15, 20, 7]

總之,前序是從左邊列開始,從上往下排。中序就是從左邊列開始,從下往上排。

看看代碼:

  1. class Solution { 
  2.     public TreeNode buildTree(int[] preorder, int[] inorder) { 
  3.         if (preorder == null || preorder.length == 0) { 
  4.             return null
  5.         } 
  6.         TreeNode root = new TreeNode(preorder[0]); 
  7.         Deque<TreeNode> stack = new LinkedList<TreeNode>(); 
  8.         stack.push(root); 
  9.         int inorderIndex = 0; 
  10.         for (int i = 1; i < preorder.length; i++) { 
  11.             int preorderVal = preorder[i]; 
  12.             TreeNode node = stack.peek(); 
  13.             if (node.val != inorder[inorderIndex]) { 
  14.                 node.left = new TreeNode(preorderVal); 
  15.                 stack.push(node.left); 
  16.             } else { 
  17.                 while (!stack.isEmpty() && stack.peek().val == inorder[inorderIndex]) { 
  18.                     node = stack.pop(); 
  19.                     inorderIndex++; 
  20.                 } 
  21.                 node.right = new TreeNode(preorderVal); 
  22.                 stack.push(node.right); 
  23.             } 
  24.         } 
  25.         return root; 
  26.     } 

if語句是為了找到左列最后一個節點,比如上述例子中的4。

while循環是當發現有右節點的時候,要找到右節點的父節點,然后添加進去。

大家可以手動試試,解法2確實不太好理解。

至少解法1的遞歸方法是要掌握的。

時間復雜度

O(n)

空間復雜度

O(n)

參考

https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/solution/

本文轉載自微信公眾號「碼上積木」,可以通過以下二維碼關注。轉載本文請聯系碼上積木公眾號。

 

責任編輯:武曉燕 來源: 碼上積木
相關推薦

2021-03-17 08:19:22

二叉樹LeetCode

2020-04-27 07:05:58

二叉樹左子樹右子樹

2021-04-28 20:12:27

數據結構創建

2013-07-15 16:35:55

二叉樹迭代器

2021-04-19 07:47:42

數據結構二叉樹Tree

2021-04-20 08:37:14

數據結構二叉樹

2021-09-29 10:19:00

算法平衡二叉樹

2020-09-23 18:25:40

算法二叉樹多叉樹

2022-10-26 23:58:02

二叉樹數組算法

2021-05-06 17:46:30

二叉樹數據結構

2020-11-02 09:15:47

算法與數據結構

2021-08-27 11:36:44

二叉樹回溯節點

2023-05-08 15:57:16

二叉樹數據結構

2018-03-15 08:31:57

二叉樹存儲結構

2021-09-15 07:56:32

二叉樹層次遍歷

2021-07-13 14:03:24

二叉樹滿二叉樹完全二叉樹

2021-12-17 14:26:58

二叉樹節點數量

2021-10-12 09:25:11

二叉樹樹形結構

2021-12-03 09:16:03

二叉樹打印平衡

2022-04-06 08:05:36

二叉樹平衡二叉樹二叉樹遍歷
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 色av一区二区三区 | 国产精品国产a级 | 国产午夜精品一区二区三区嫩草 | 国产亚洲网站 | 91久久| 亚洲成人高清 | 美女一区| 一区二区视频在线 | 久久久久久国产精品免费免费 | 欧美精品一区二区免费 | 国产精品久久av | 国产免费又色又爽又黄在线观看 | 国产精品久久久久久久久久久久久久 | 欧美国产日韩在线观看 | 欧美成人精品二区三区99精品 | 欧美激情精品久久久久久 | 国产精品视频一二三区 | 在线视频一区二区三区 | 久久天天综合 | 欧美性生活一区二区三区 | 国产97色| 日韩在线免费 | 日本黄色短片 | 天天影视网天天综合色在线播放 | 国产激情91久久精品导航 | 激情网五月天 | 毛片一区二区三区 | 亚洲成人a v | 成人免费视频 | 日韩网| 91免费观看| 奇色影视 | 亚洲精品久久久久久久久久久 | 成人网视频 | 国产综合av| 一级片av | 日韩精品一区二区在线 | 国产农村妇女毛片精品久久麻豆 | 欧美一级片在线 | 日韩视频一区 | 成人国产精品久久 |