LeetCode-1008. 前序遍歷構造二叉搜索樹【棧 樹 二叉搜索樹 數組 二叉樹 單調棧】

LeetCode-1008. 前序遍歷構造二叉搜索樹【棧 樹 二叉搜索樹 數組 二叉樹 單調棧】

  • 題目描述:
  • 解題思路一:題目大致意思就是給定一個二叉樹的前序遍歷,求對應的二叉搜索樹。一種比較特殊的點是「二叉搜索樹」的中序遍歷的結果是【有序序列】,故而我們可以對「前序遍歷」的結果 【排序】 得到「中序遍歷」的結果。從而依據這棵樹的前序和中序遍歷結果構建該「二叉搜索樹」。
  • 解題思路二:二分查找左右子樹的分界線遞歸構建左右子樹。可以找到的規律是前序遍歷結果第一個是根節點,而后面的元素可以分為兩個連續的數組,一個數組所有元素嚴格小于根節點,另一個數組所有元素嚴格大于根節點。困難在于快速找到這兩個數組的分界線,這里用的是二分法。
  • 解題思路三:根據數值上下界遞歸構建左右子樹,我們使用遞歸的方法,在掃描先序遍歷的同時構造出二叉樹。我們在遞歸時維護一個 (lower, upper) 二元組,表示當前位置可以插入的節點的值的上下界。如果此時先序遍歷位置的值處于上下界中,就將這個值作為新的節點插入到當前位置,并遞歸地處理當前位置的左右孩子的兩個位置。否則回溯到當前位置的父節點。
  • 解題思路四:單調棧,思路是維護一個棧頂小棧頂大的單調棧,遍歷一遍前序遍歷結果。如果當前元素大于棧頂元素,則循環出棧找到其父節點node。如果父節點的元素值小于子節點的元素值,則子節點為右孩子,否則為左孩子。代碼邏輯其實很簡單。

題目描述:

給定一個整數數組,它表示BST(即 二叉搜索樹 )的 先序遍歷 ,構造樹并返回其根。

保證 對于給定的測試用例,總是有可能找到具有給定需求的二叉搜索樹。

二叉搜索樹 是一棵二叉樹,其中每個節點, Node.left 的任何后代的值 嚴格小于 Node.val , Node.right 的任何后代的值 嚴格大于 Node.val。

二叉樹的 前序遍歷 首先顯示節點的值,然后遍歷Node.left,最后遍歷Node.right。

示例 1:
請添加圖片描述
輸入:preorder = [8,5,1,7,10,12]
輸出:[8,5,10,1,7,null,12]

示例 2:
輸入: preorder = [1,3]
輸出: [1,null,3]

提示:
1 <= preorder.length <= 100
1 <= preorder[i] <= 10^8
preorder 中的值 互不相同

解題思路一:題目大致意思就是給定一個二叉樹的前序遍歷,求對應的二叉搜索樹。一種比較特殊的點是「二叉搜索樹」的中序遍歷的結果是【有序序列】,故而我們可以對「前序遍歷」的結果 【排序】 得到「中序遍歷」的結果。從而依據這棵樹的前序和中序遍歷結果構建該「二叉搜索樹」。

對應的題目是105. 從前序與中序遍歷序列構造二叉樹,感興趣的可以看看。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:def bstFromPreorder(self, preorder: List[int]) -> Optional[TreeNode]:inorder = sorted(preorder)def myBST(preorder_left: int, preorder_right: int, inorder_left: int, inorder_right: int):if preorder_left > preorder_right:return None# 前序遍歷中的第一個節點就是根節點preorder_root = preorder_left# 在中序遍歷中定位根節點inorder_root = index[preorder[preorder_root]]# 先把根節點建立出來root = TreeNode(preorder[preorder_root])# 得到左子樹中的節點數目size_left_subtree = inorder_root - inorder_left# 遞歸地構造左子樹,并連接到根節點# 先序遍歷中「從 左邊界+1 開始的 size_left_subtree」個元素就對應了中序遍歷中「從 左邊界 開始到 根節點定位-1」的元素root.left = myBST(preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1)# 遞歸地構造右子樹,并連接到根節點# 先序遍歷中「從 左邊界+1+左子樹節點數目 開始到 右邊界」的元素就對應了中序遍歷中「從 根節點定位+1 到 右邊界」的元素root.right = myBST(preorder_left + 1 + size_left_subtree, preorder_right, inorder_root + 1, inorder_right)return rootn = len(preorder)index = {element: i for i, element in enumerate(inorder)}return myBST(0, n-1, 0, n-1)

構造哈希表的目的是為了,O(1)時間找到中序遍歷結果中的根節點。
時間復雜度:O(nlogn)排序的結果,構造二叉搜索樹的時間復雜度為 O(n)
空間復雜度:O(n)

解題思路二:二分查找左右子樹的分界線遞歸構建左右子樹。可以找到的規律是前序遍歷結果第一個是根節點,而后面的元素可以分為兩個連續的數組,一個數組所有元素嚴格小于根節點,另一個數組所有元素嚴格大于根節點。困難在于快速找到這兩個數組的分界線,這里用的是二分法。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:def bstFromPreorder(self, preorder: List[int]) -> Optional[TreeNode]:def dfs(preorder: List[int], left: int, right: int):if left > right: return Noneroot = TreeNode(preorder[left])if left == right: return rootl, r = left, rightwhile(l < r):mid = int(l + (r - l + 1) / 2)if preorder[mid] < preorder[left]: l = mid # 轉到區間[mid, r]else : r = mid -1 # 轉到區間[l, mid -1]# 其實最后l=r是最終的分界線root.left = dfs(preorder, left + 1, l)root.right = dfs(preorder, l + 1, right)return rootn = len(preorder)if n==0: return nullreturn dfs(preorder, 0, n-1)

時間復雜度:O(nlogn),在找左右子樹分界線的時候時間復雜度為O(logn);
空間復雜度:O(n)

解題思路三:根據數值上下界遞歸構建左右子樹,我們使用遞歸的方法,在掃描先序遍歷的同時構造出二叉樹。我們在遞歸時維護一個 (lower, upper) 二元組,表示當前位置可以插入的節點的值的上下界。如果此時先序遍歷位置的值處于上下界中,就將這個值作為新的節點插入到當前位置,并遞歸地處理當前位置的左右孩子的兩個位置。否則回溯到當前位置的父節點。

請添加圖片描述

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:def bstFromPreorder(self, preorder: List[int]) -> Optional[TreeNode]:n = len(preorder)index = 0def dfs(lowerBound: int, upperBound: int):nonlocal index  # 將index聲明為非局部變量if index == n: return Nonecur = preorder[index]if cur < lowerBound or cur > upperBound: return Noneindex += 1root = TreeNode(cur)root.left = dfs(lowerBound, cur)root.right = dfs(cur, upperBound)return rootif n==0: return nullreturn dfs(float('-inf'), float('inf'))

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

解題思路四:單調棧,思路是維護一個棧頂小棧頂大的單調棧,遍歷一遍前序遍歷結果。如果當前元素大于棧頂元素,則循環出棧找到其父節點node。如果父節點的元素值小于子節點的元素值,則子節點為右孩子,否則為左孩子。代碼邏輯其實很簡單。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:def bstFromPreorder(self, preorder: List[int]) -> Optional[TreeNode]:n = len(preorder)if n==0: return nullroot = TreeNode(preorder[0])stack= [root]for i in range(1,n,1):node = stack[-1]currentNode = TreeNode(preorder[i])while stack and stack[-1].val < currentNode.val: node = stack.pop()if node.val < currentNode.val: node.right = currentNodeelse : node.left = currentNodestack.append(currentNode)return root

時間復雜度:O(n)僅掃描前序遍歷一次。
空間復雜度:O(n)用來存儲棧和二叉樹。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/214758.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/214758.shtml
英文地址,請注明出處:http://en.pswp.cn/news/214758.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【UE5】監控攝像頭效果(下)

目錄 效果 步驟 一、多攝像機視角切換 二、攝像頭自動旋轉巡視 三、攝像頭跟蹤拍攝 效果 步驟 一、多攝像機視角切換 1. 打開玩家控制器“MyPlayerController”&#xff0c;添加一個變量&#xff0c;命名為“BP_SecurityCameraArray”&#xff0c;類型為“BP_SecurityCa…

蛋仔派對巔峰對決驚奇舞臺必勝打法

Hello!大家好呀&#xff01;蛋仔派對我也開始玩啦&#xff01;本期我們發一個蛋仔派對巔峰對決驚奇舞臺的必勝打法吧&#xff01;&#xff08;題外話&#xff1a;我的蛋仔名叫做 酷影kuying 大家能加我的好友嗎&#xff1f;我是新手有老手能帶我上分嘛&#xff1f;…

第二十四章 STL-函數對象

一、函數對象 1、函數對象概念 概念&#xff1a; 重載函數調用操作符的類&#xff0c;其對象常稱為函數對象 函數對象使用重載的()時&#xff0c;行為類似函數調用&#xff0c;也叫仿函數 本質&#xff1a; 函數對象(仿函數)是一個類&#xff0c;不是一個函數 2、函數對…

[方法論]allocation 空間內容分配

區分度 typeanalysisrecognitionconclusion type - 閱讀 - 理解- 背誦- 聽課 看 聽 思考- reproduce/ 默寫/ 應用- 背- 想- 寫analysis 理解 和 背 是不占用現實空間的&#xff0c;可以在腦內不斷消化&#xff0c;可以飛配給沒有空間的時間塊。 閱讀 和 寫是占用現實空間的…

企業如何選擇合適的信息化管理系統?

一、什么是信息化管理系統 信息化這個詞在近年已經被說爛了&#xff0c;在信息化快速發展的時代&#xff0c;越來越多的企業開始意識到信息化管理系統的重要性。信息化管理系統是指一種能夠幫助企業或組織有效管理信息資源&#xff0c;提高信息的可靠性、安全性和有效性的軟件…

博世汽車產業轉型,裁1500人 | 百能云芯

博世&#xff08;Bosch&#xff09;&#xff0c;作為全球領先的汽車零部件制造商&#xff0c;近日宣布了一項戰略性的組織調整計劃&#xff0c;以更好地適應不斷演變的汽車行業需求和技術革新。根據《路透社》的報道&#xff0c;博世計劃在2025年底之前&#xff0c;在其位于德國…

【OD2023C卷真題】20天拿下華為OD筆試之【排序】2023C-身高提供排序【歐弟算法】全網注釋最詳細分類最全的華為OD真題題解

文章目錄 題目描述與示例題目描述輸入描述輸出描述示例一輸入輸出 示例二輸入輸出 解題思路代碼時空復雜度 進階華為OD算法/大廠面試高頻題算法練習沖刺訓練 題目描述與示例 題目描述 某學校舉行運動會,學生們按編號(1、2、3.....n) 進行標識, 現需要按照身高由低到高排列&a…

Redis基礎系列-主從復制

Redis基礎系列-主從復制 文章目錄 Redis基礎系列-主從復制1. 什么是 Redis 主從復制&#xff1f;2. 主從復制有什么好處&#xff1f;3. 如何配置 Redis 主從復制&#xff1f;4. 主從復制的驗證4.1 如何查看主從搭建成功4.2 主從常見疑問4.3 主從常見命令 5. 主從復制的原理和工…

掌握1688官方API接口:開啟智能商務合作新篇章

當涉及到與1688官方合作的API接口時&#xff0c;以下是一些建議和指導&#xff0c;以幫助您開始編寫相關的代碼。 了解API接口文檔&#xff1a; 在編寫與1688官方合作的API接口之前&#xff0c;首先需要了解1688官方提供的API接口文檔。您可以在1688開放平臺上找到相關的文檔…

12.11 作業

1&#xff0c; 完善對話框&#xff0c;點擊登錄對話框&#xff0c;如果賬號和密碼匹配&#xff0c;則彈出信息對話框&#xff0c;給出提示”登錄成功“&#xff0c;提供一個Ok按鈕&#xff0c;用戶點擊Ok后&#xff0c;關閉登錄界面&#xff0c;跳轉到其他界面 如果賬號和密碼…

王道數據結構課后代碼題p150 第13——17 (c語言代碼實現)

目錄 13.p 和 q 分別為指向該二叉樹中任意兩個結點的指針&#xff0c;試編寫算法 ANCESTOR(ROOT,P,q,r)&#xff0c;找到P和q的最近公共祖先結點 r 14.假設二叉樹采用二叉鏈表存儲結構&#xff0c;設計一個算法&#xff0c;求非空二叉樹 b的寬度(即具有結點數最多的那一層的結點…

Draw.io繪圖操作

使用步驟 以下是使用 draw.io&#xff08;現在的 diagrams.net&#xff09;的一些基本操作步驟&#xff1a; 訪問網站&#xff1a; 打開瀏覽器&#xff0c;訪問 https://app.diagrams.net/。 創建新文檔&#xff1a; 在 diagrams.net 主頁&#xff0c;點擊 “New Diagram” 或…

2023最新vue安裝(npm,yarn,國內鏡像,vue安裝,vue導包)全套教程2023年12月最新

第一步(安裝npm) 官網地址&#xff1a;https://nodejs.org/en/download windows安裝yarn 詳細教程_windows yarn-CSDN博客 第二步&#xff08;yarn下載&#xff09; windows 下需要下載msi文件 &#xff0c;下載地址&#xff1a;https://yarnpkg.com/latest.msi npm install -g…

力扣198. 打家劫舍

動態規劃 思路&#xff1a; 尋找狀態轉移方程&#xff1a; 假設有 n 個房間&#xff1b; 如果偷第 n 個房間&#xff0c;那么第 n - 1 個房間不偷&#xff0c;之前的 n - 2 個房間偷竊到了 M(n - 2)&#xff0c;總共可以偷竊到 M(n - 2) N(n)&#xff1b;如果不偷第 n 個房間…

第11節: Vue3 動態參數

在UniApp中使用Vue3框架使用動態參數&#xff1a; <template> <view> <text>{{ dynamicText }}</text> <button click"changeText">點擊改變文本</button> </view> </template> <script> export de…

SD-WAN解決企業國際互聯組網需求

隨著云計算、移動應用和企業全球化的浪潮&#xff0c;實時應用在不同地點之間的傳輸需求不斷增加&#xff0c;涵蓋異地辦公、視頻會議、遠程桌面、支付交易系統以及遠程醫療等。這些應用的順暢傳輸對于企業至關重要&#xff0c;而SD-WAN&#xff08;軟件定義廣域網&#xff09;…

Spring MVC詳解、靜態資源訪問、攔截器

1. Spring MVC概述 1.1 Spring MVC是什么 SpringMVC是Spring的一個模塊&#xff0c;是一個基于MVC設計模式的web框架。 1.2 Spring MVC執行流程。 1.3 組件分析 前端控制器&#xff08;默認配置&#xff09;Dispatcher Servlet 作用&#xff1a;只負責分發請求。可以很好的對…

這樣的軟件測試面試題,誰面試遇到誰淘汰!!!

88 11.6 自動化測試用例的來源 手工編寫測試用例 把原來手工的測試用例&#xff0c;當成自動化測試用例 11.7 自動化測試的優點與缺點 優點: 1、對程序的回歸測試更方便 2、可以運行更多更繁瑣的測試 3、提高測試效率和準確性&#xff0c;節約時間成本 4、可以執行一些手工測試…

【源碼解析】從ReentrantLock角度聊聊AQS原理

AQS結構 //頭節點 當前持有鎖的線程private transient volatile Node head;/*** Tail of the wait queue, lazily initialized. Modified only via* method enq to add new wait node.*///每個進來的線程都插入到最后private transient volatile Node tail;/*** The synchroni…

MLIR筆記(6)

5. 方言與操作 5.1. 方言的概念 在MLIR里&#xff0c;通過Dialect類來抽象方言。具體的每種方言都需要從這個基類派生一個類型&#xff0c;并實現重載自己所需的虛函數。 MLIR文檔里這樣描述方言&#xff08; MLIR Language Reference - MLIR&#xff09;&#xff1a; 方言…