LeetCode Day5 -- 二叉樹

目錄

1.?啥時候用二叉樹?

(1)典型問題

(2)核心思路

2.?BFS、DFS、BST

2.1 廣度優先搜索BFS

(1)適用任務

(2)解決思路??:使用隊列逐層遍歷

2.2?深度優先搜索DFS

(1)三種變體(前中后序)

(2)解決思路:遞歸實現

2.3?二叉搜索樹BST

3.?LeetCode

3.1 BFS

(1)199?二叉樹的右視圖

(2)1161?最大層內元素和

3.2?DFS

(1)104 二叉樹的最大深度

(2)872?葉子相似的樹

(3)1448?統計二叉樹中好節點的數目

(4)1372?二叉樹中的最長交錯路徑

(5)236?二叉樹的最近公共祖先

3.3?BST

(1)700?二叉搜索樹中的搜索

(2)450?刪除二叉搜索樹中的節點

(3)98?驗證二叉搜索樹

(4)230?二叉搜索樹中第k小的元素


1.?啥時候用二叉樹?

(1)典型問題

  • 分層數據處理(文件系統、組織架構)

  • 高效搜索(BST中查找/插入/刪除)

  • 路徑問題(根節點到葉節點的路徑)

  • 樹形結構操作(鏡像、深度、平衡性判斷)

  • 表達式解析(語法樹)

(2)核心思路

def solve(root):if root is None:  # 關鍵:始終先處理空節點return base_value  # 如深度為0,路徑為空列表等# 遞歸分解子問題left_result = solve(root.left)     # 處理左子樹right_result = solve(root.right)   # 處理右子樹# 合并結果(根據問題類型選擇策略)return combine(root.val, left_result, right_result)

2.?BFS、DFS、BST

2.1 廣度優先搜索BFS

(1)適用任務

-- 層序遍歷(按層級輸出節點)

-- 最短路徑(根節點到目標節點的最小深度)

-- 尋找最近鄰節點

(2)解決思路??:使用隊列逐層遍歷

from collections import dequedef bfs(root):if not root: return []queue = deque([root])result = []while queue:level = []for _ in range(len(queue)):  # 遍歷當前層node = queue.popleft()level.append(node.val)if node.left: queue.append(node.left)if node.right: queue.append(node.right)result.append(level)  # 保存當前層結果return result

2.2?深度優先搜索DFS

(1)三種變體(前中后序)

遍歷方式??

應用場景

??解決任務??

??操作順序??

??前序遍歷??

節點初始化、路徑記錄、自頂向下操作

復制樹、表達式前綴表示

根 → 左 → 右

??中序遍歷??

二叉搜索樹操作、順序相關處理

BST升序輸出、表達式解析

左 → 根 → 右

??后序遍歷??

子樹信息統計、依賴子樹結果的操作

子樹統計、內存釋放

左 → 右 → 根

關鍵判斷依據:??當前節點操作與子樹操作的關系?

  1. 如果操作依賴子樹結果 → 用后序遍歷(如:樹深度、子樹統計)

  2. 如果操作在前子樹操作前必須完成 → 用前序遍歷(如:路徑記錄、節點初始化)

  3. 如果涉及順序處理 → 用中序遍歷(如:BST中序遍歷有序)

(2)解決思路:遞歸實現

""" 前序遍歷 """
def preorder(root):if not root: returnprint(root.val)          # 先操作根節點preorder(root.left)preorder(root.right)""" 中序遍歷 (BST關鍵) """
def inorder(root):if not root: returninorder(root.left)print(root.val)          # 在中間操作節點inorder(root.right)""" 后序遍歷 """
def postorder(root):if not root: returnpostorder(root.left)postorder(root.right)print(root.val)          # 最后操作根節點

2.3?二叉搜索樹BST

左子樹節點值 <?根節點值 <?右子樹節點值

??(1)典型任務??

-- 查找元素(時間復雜度 ??O(log n)??)

-- 插入/刪除節點(保持BST性質)

-- 范圍查詢(如找出值在 [low, high] 間的節點)

(2)代碼模板

""" BST查找 """
def search(root, target):while root:if root.val == target: return Trueroot = root.left if target < root.val else root.rightreturn False""" BST插入(遞歸版)"""
def insert(root, val):if not root: return TreeNode(val)if val < root.val: root.left = insert(root.left, val)elif val > root.val: root.right = insert(root.right, val)return root  # 返回更新后的子樹根節點""" 驗證BST(中序遍歷應用)"""
def isValidBST(root):stack, prev = [], float('-inf')while stack or root:while root:  # 深入左子樹stack.append(root)root = root.leftroot = stack.pop()if root.val <= prev: return False  # 破壞升序prev = root.valroot = root.right  # 轉向右子樹return True

3.?LeetCode

3.1 BFS

(1)199?二叉樹的右視圖

給定一個二叉樹的?根節點?root,想象自己站在它的右側,按照從頂部到底部的順序,返回從右側所能看到的節點值。

本質上就是二叉樹每一層的最后一個入隊的節點

from collections import deque
class Solution(object):def rightSideView(self, root):""":type root: Optional[TreeNode]:rtype: List[int]"""if not root: return []result=[]quene = deque([root])while quene:size=len(quene)for i in range(size):node = quene.popleft()if node.left: quene.append(node.left)if node.right:quene.append(node.right)cur_level_last = node.valresult.append(cur_level_last)return result

(2)1161?最大層內元素和

給你一個二叉樹的根節點?root。設根節點位于二叉樹的第?1?層,而根節點的子節點位于第?2?層,依此類推。請返回層內元素之和最大的那幾層(可能只有一層)的層號,并返回其中最小的那個。

from collections import deque
class Solution(object):def maxLevelSum(self, root):""":type root: Optional[TreeNode]:rtype: int"""if not root: return 0quene = deque([root])level=1max_sum=[root.val, level]while quene:level_sum = 0level += 1for i in range(len(quene)):node = quene.popleft()level_sum += node.valif node.left: quene.append(node.left)if node.right:quene.append(node.right)if max_sum[0]<level_sum:max_sum = [level_sum, level-1]return max_sum[1]

3.2?DFS

(1)104 二叉樹的最大深度

給定一個二叉樹?root?,返回其最大深度。二叉樹的?最大深度?是指從根節點到最遠葉子節點的最長路徑上的節點數。

DFS方法:后序遍歷,先看左右子樹的深度,更深的+1即為整棵樹的最大深度。

class Solution(object):def maxDepth(self, root):""":type root: Optional[TreeNode]:rtype: int"""if not root:return 0left_depth = self.maxDepth(root.left)right_depth = self.maxDepth(root.right)return max(left_depth,right_depth)+1

BFS方法:

from collections import deque
class Solution(object):def maxDepth(self, root):""":type root: Optional[TreeNode]:rtype: int"""if not root:return 0quene = deque([root])   ## 隊列中存的是當前層的所有節點result = []             ## 用來保存每一層的節點while quene:cur_level = []              ## 當前層的節點level_size = len(quene)     ## 當前層有幾個節點for i in range(level_size):node = quene.popleft()  cur_level.append(node.val)  ## 將當前節點加入當前層中if node.left:   quene.append(node.left)if node.right:  quene.append(node.right)result.append(cur_level)return len(result)   

(2)872?葉子相似的樹

如果有兩棵二叉樹的葉值序列是相同,那么我們就認為它們是?葉相似?的。如果給定的兩個根結點分別為?root1?和?root2?的樹是葉相似的,則返回?true;否則返回?false?。

DFS遍歷都是先左后右的,因此均能保證葉子節點的順序。

from collections import deque
class Solution(object):def find_leaves(self,root,leaves):if not root:    return[]left_leaves = self.find_leaves(root.left,leaves)if not root.left and not root.right:leaves.append(root.val)right_leaves = self.find_leaves(root.right,leaves)return leavesdef leafSimilar(self, root1, root2):""":type root1: Optional[TreeNode]:type root2: Optional[TreeNode]:rtype: bool"""leaves1=[]leaves2=[]leaves1 = self.find_leaves(root1,leaves1)leaves2 = self.find_leaves(root2,leaves2)if leaves1==leaves2:return Trueelse:return False

(3)1448?統計二叉樹中好節點的數目

給你一棵根為?root?的二叉樹,請你返回二叉樹中好節點的數目。「好節點」X 定義為:從根到該節點 X 所經過的節點中,沒有任何節點的值大于 X 的值。

采用前序遍歷(根 → 左 → 右)

根節點優先處理??:在訪問子節點前先判斷當前節點,符合路徑順序

及時更新最大值??:當遇到更大節點時,立即更新路徑最大值傳遞給子節點

class Solution(object):def dfs(self,root,cur_max):if not root:    return 0count = 0if root.val>=cur_max:count=1cur_max = root.valcount += self.dfs(root.left,cur_max)count += self.dfs(root.right,cur_max)return countdef goodNodes(self, root):""":type root: Optional[TreeNode]:rtype: int"""cur_max=-10001return self.dfs(root,cur_max)

(4)1372?二叉樹中的最長交錯路徑

給你一棵以?root?為根的二叉樹,二叉樹中的交錯路徑定義如下:

  • 選擇二叉樹中?任意?節點和一個方向(左或者右)。
  • 如果前進方向為右,那么移動到當前節點的的右子節點,否則移動到它的左子節點。
  • 改變前進方向:左變右或者右變左。
  • 重復第二步和第三步,直到你在樹中無法繼續移動。

交錯路徑的長度定義為:訪問過的節點數目 - 1(單個節點的路徑長度為 0 )。請你返回給定樹中最長?交錯路徑?的長度。

使用后序遍歷:①當前節點的狀態計算??依賴子節點狀態??

②需要先知道子節點的?left_path 和?right_path 才能計算當前節點

class Solution(object):def longestZigZag(self, root):""":type root: Optional[TreeNode]:rtype: int"""    self.max_path = 0def dfs(node):"""后序遍歷返回(left_path, right_path)""""""left_path: 從當前節點出發,第一步向左走能形成的最長交錯路徑長度""""""right_path: 從當前節點出發,第一步向右走能形成的最長交錯路徑長度"""if not node:return (0, 0)left_res = dfs(node.left)  right_res = dfs(node.right)"""從當前節點向左走一步到左子節點(+1)然后需要向右走,查詢左子節點的??向右走狀態??(right_path,即left_res[1])"""left_path = 1 + left_res[1] if node.left else 0  """從當前節點向右走一步到右子節點(+1)然后需要向左走,查詢右子節點向左走的狀態(left_path,即right_res[0])"""right_path = 1 + right_res[0] if node.right else 0self.max_path = max(self.max_path, left_path, right_path)return (left_path, right_path)dfs(root)return self.max_path

(5)236?二叉樹的最近公共祖先

祖先可能的情況:

(1)p 和 q 分屬不同子樹 → 當前根節點是 LCA

(2)p 和 q 在同一子樹 → LCA 在該子樹中

(3)p 或 q 自身就是 LCA(祖孫關系)

→?采用后序遍歷順序??(左右根):

先深入子樹尋找節點,再處理當前節點判斷邏輯

class Solution(object):def lowestCommonAncestor(self, root, p, q):""":type root: TreeNode:type p: TreeNode:type q: TreeNode:rtype: TreeNode"""if not root or root==p or root==q:return rootleft = self.lowestCommonAncestor(root.left,p,q)     ## 在左子樹中找到的p或q(或LCA)right = self.lowestCommonAncestor(root.right,p,q)   ## 在右子樹中找到的p或q(或LCA)if left and right:  ## p和q分別在root的左右子樹中 return root     ## root是它們最低層級的共同祖先if left:            ## 兩個節點必定都在左子樹中## 此時left要么是p和q中的一個(如果尚未找到兩者關系),要么是p和q的LCA(如果已找到兩者關系)return left     return right

3.3?BST

(1)700?二叉搜索樹中的搜索

給定二叉搜索樹(BST)的根節點?root?和一個整數值?val。你需要在 BST 中找到節點值等于?val?的節點。 返回以該節點為根的子樹。 如果節點不存在,則返回?null?。

class Solution(object):def searchBST(self, root, val):""":type root: Optional[TreeNode]:type val: int:rtype: Optional[TreeNode]"""if not root: return nullwhile root:if root.val==val:return rootelif root.val<val:root=root.rightelse:root=root.left

(2)450?刪除二叉搜索樹中的節點

要被刪除的節點存在三種情況:

1. 葉子節點??:直接刪除(返回None)

??2. 只有一個子節點??:用子節點替代當前節點

實現:直接返回子節點是讓父節點直接指向孫子節點

??3. 有兩個子節點??:找到前置節點(當前節點左子樹中最右側節點)替換

實現:用前置節點值覆蓋當前節點值?→ 刪除前置節點(遞歸調用)

class Solution(object):def deleteNode(self, root, key):""":type root: Optional[TreeNode]:type key: int:rtype: Optional[TreeNode]"""if not root: return Noneif key>root.val:    ## key比當前節點大,在右子樹中刪root.right=self.deleteNode(root.right,key)elif key<root.val:  ## key比當前節點小,在左子樹中刪root.left=self.deleteNode(root.left,key)else:       ## 找到要刪的節點了,有以下4種情況""" 1.當前節點是葉子節點 → 直接刪除"""if not root.left and not root.right:return None""" 2.當前節點只有左孩子 → 直接用左孩子替代當前節點"""elif not root.right:return root.left""" 3.當前節點只有右孩子 → 直接用右孩子替代當前節點 """elif not root.left:return root.right""" 4. 當前節點左右孩子都有 → 用左子樹的最右側節點替代 """else:## 尋找前置節點pre = root.left     while pre.right:pre=pre.right## 前置節點值賦給當前節點root.val = pre.val ## 刪除原前置節點 root.left = self.deleteNode(root.left,pre.val)return root

(3)98?驗證二叉搜索樹

方案一:遞歸實現

每個節點都有值范圍約束:(low,high)

左子樹繼承上界:(low,node.val),右子樹繼承下界:(node.val,high)

class Solution(object):def isValidBST(self, root):""":type root: Optional[TreeNode]:rtype: bool"""def validate(node, low=float('-inf'), high=float('inf')):if not node:return Trueif node.val<=low or node.val>=high:return Falseis_left = validate(node.left, low, node.val)is_right = validate(node.right, node.val, high)return is_left and is_rightreturn validate(root)

方案二:中序遍歷驗證

使用模擬中序遍歷過程,比較當前節點與前一個節點的值

class Solution(object):def isValidBST(self, root):stack=[]pre=Nonewhile stack or root:""" 左 """while root:     stack.append(root)root=root.left""" 根 """root=stack.pop()if pre is not None and root.val<=pre:   return False    ## 當前值比pre值(其左側)小""" 右 """pre=root.valroot=root.rightreturn True

(4)230?二叉搜索樹中第k小的元素

因為搜索樹的中序遍歷得到一個遞增序列,所以本質上就是求中序遍歷的第k個值。

class Solution(object):def kthSmallest(self, root, k):""":type root: Optional[TreeNode]:type k: int:rtype: int"""stack=[]count=0while root or stack:## 左while root:stack.append(root)root=root.left## 根root=stack.pop()count+=1if count==k:   ## 是否是第k個 return root.val## 右root=root.right

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

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

相關文章

<c1:C1DateTimePicker的日期時間控件,控制日期可以修改,時間不能修改,另外控制開始時間的最大值比結束時間小一天

兩個時間控件 <c1:C1DateTimePicker Width"170" EditMode"DateTime" CustomDateFormat"yyyy-MM-dd" CustomTimeFormat"HH:mm:ss" Style"{StaticResource ListSearch-DateTimePicker}" x:Name"dateTimePicker"…

文件完整性監控工具:架構和實現

文件完整性監控(FIM)作為一道關鍵的防御層&#xff0c;確保系統和網絡中文件及文件夾的完整性與安全性。文件完整性監控工具通過監控關鍵文件的變更并檢測未經授權的修改&#xff0c;提供關于潛在安全漏洞、惡意軟件感染和內部威脅的早期警報。為了使文件完整性監控工具發揮實效…

Linux信號量和信號

1.溫故知新上一篇博客&#xff0c;我們又知道了一種進程間通信的方案&#xff1a;共享內存。它是在物理內存中用系統調用給我們在物理內存開辟一個共享內存&#xff0c;可以由多個進程的頁表進行映射&#xff0c;共享內存不和管道一樣&#xff0c;它的生命周期是隨內核的&#…

騰訊測試崗位面試真題分析

以下是對騰訊測試工程師面試問題的分類整理、領域占比分析及高頻問題精選&#xff08;基于??92道問題&#xff0c;總出現次數118次??&#xff09;。問題按??7大技術領域??劃分&#xff0c;高頻問題標注優先級&#xff08;1-5&#x1f31f;&#xff09;&#xff1a; 不…

全面解析遠程桌面:功能實現、性能優化與安全防護全攻略

遠程桌面技術已成為工作與生活中不可或缺的協作工具&#xff0c;但在實際應用中&#xff0c;用戶常遇到連接失敗、卡頓延遲、安全隱患等問題。本文從遠程桌面功能原理、網絡與性能優化、安全防護策略、跨平臺兼容性等角度&#xff0c;詳細解析常見問題的解決方案&#xff0c;并…

【問題】Mybatis-plus框架使用@Select注解編寫查詢SQL,json字段查詢轉換失敗

問題描述在使用mybaits-plus的時候定義的Mapper接口實現了BaseMapper&#xff0c;沒有編寫Mapper對應的xml&#xff0c;大部分查詢使用框架的接口進行查詢基本屬性返回都是正常&#xff0c;復雜對象在sql中會進行查詢&#xff0c;但是返回對象中卻未包含相關屬性。問題原因 沒有…

Python多線程實現大文件下載

Python多線程實現大文件下載 在互聯網時代&#xff0c;文件下載是日常操作之一&#xff0c;尤其是大文件&#xff0c;如軟件安裝包、高清視頻等。然而&#xff0c;網絡條件不穩定或帶寬有限時&#xff0c;下載速度會變得很慢&#xff0c;令人抓狂。幸運的是&#xff0c;通過多線…

【R語言】RStudio 中的 Source on Save、Run、Source 辨析

RStudio 中的 Source on Save、Run、Source 辨析 在使用 RStudio 進行 R 語言開發時&#xff0c;我們會在主界面左上角看見三個按鈕&#xff1a;Source on Save、Run、Source 。 本文將帶你從概念、使用方法、快捷鍵、使用場景以及注意事項等方面詳細解析這三個功能。 文章目錄…

藍橋杯算法之搜索章 - 4

目錄 文章目錄 前言 一、記憶化搜索 二、題目概略 三、斐波拉契數 四、Function 五、天下第一 六、滑雪 總結 親愛的讀者朋友們&#xff0c;大家好啊&#xff01;不同的時間&#xff0c;相同的地點&#xff0c;今天又帶來了關于搜索部分的講解。接下來我將接著我前面文章的內容…

抗量子加密技術前瞻:后量子時代的密碼學革命

目錄抗量子加密技術前瞻&#xff1a;后量子時代的密碼學革命1. 量子計算威脅現狀1.1 量子霸權里程碑1.2 受威脅算法1.3 時間緊迫性2. 抗量子密碼學體系2.1 技術路線對比2.2 數學基礎革新3. 標準化進程3.1 NIST PQC標準化時間線3.2 當前推薦算法4. 技術實現方案4.1 Kyber密鑰交換…

基于STM32設計的礦山環境監測系統(NBIOT)_262

文章目錄 一、前言 1.1 項目介紹 【1】開發背景 【2】研究的意義 【3】最終實現需求 【4】項目硬件模塊組成 1.2 設計思路 【1】整體設計思路 【2】上位機開發思路 1.3 項目開發背景 【1】選題的意義 【2】摘要 【3】國內外相關研究現狀 【5】參考文獻 1.4 開發工具的選擇 【1】…

電腦如何安裝win10專業版_電腦用u盤安裝win10專業版教程

電腦如何安裝win10專業版&#xff1f;電腦還是建議安裝win10專業版。Win分為多個版本&#xff0c;其中家庭版&#xff08;Home&#xff09;和專業版&#xff08;Pro&#xff09;是用戶選擇最多的兩個版本。win10專業版在功能以及安全性方面有著明顯的優勢&#xff0c;所以電腦還…

多語言文本 AI 情感分析 API 數據接口

多語言文本 AI 情感分析 API 數據接口 AI / 文本處理 AI 模型快速分析文本情感傾向 多語言文本 / 情感分析。 1. 產品功能 支持多語言文本情感分析&#xff1b;基于特定 AI 模型&#xff0c;快速識別文本情感傾向&#xff1b;適用于評論分析、輿情監控等場景&#xff1b;全接…

【R語言】R語言的工作空間映像(workspace image,通常是.RData)詳解

R語言的工作空間映像&#xff08;.RData&#xff09;詳解 在使用 R 語言時&#xff0c;你可能會注意到&#xff0c;每次退出 R 會彈出一個提示&#xff1a; Save workspace image? [y/n/c] 如果你使用的是 Rstudio 這個 IDE 來進行R語言的開發&#xff0c;那么可能彈出的提示…

在線 A2C實踐

在線 A2C&#xff08;Actor-Critic&#xff09;算法在推薦系統中的實踐&#xff0c;核心是將推薦過程建模為實時交互的強化學習問題&#xff0c;通過 Actor 生成推薦策略、Critic 評估策略價值&#xff0c;實現 “決策 - 反饋 - 更新” 的閉環。從樣本設計到最終上線&#xff0…

Eclipse RCP產品動態模塊設計

文章目錄 遇到問題具體實踐效果演示應用下載 遇到問題 如果你是一個To C產品的設計者&#xff0c;勢必會遇到用戶需求高度分化的場景&#xff0c;隨之而來的是繁雜的功能列表&#xff0c;如何讓用戶只接觸與其任務直接相關的功能&#xff0c;隱藏無關元素&#xff1f; 具體實…

NLP自然語言處理: FastText工具與遷移學習基礎詳解

FastText工具與遷移學習基礎詳解 一、知識框架總覽 FastText工具核心功能與應用場景FastText模型架構與工作原理層次Softmax加速機制哈夫曼樹概念與構建方法 二、FastText工具核心解析 2.1 功能定位 雙重核心功能 文本分類&#xff1a;可直接用于文本分類任務&#xff0c;快速生…

uni-app 生命周期詳解

概述 uni-app 基于 Vue.js 框架開發&#xff0c;其生命周期包含了三個層面&#xff1a; 應用生命周期&#xff1a;App.vue 的生命周期頁面生命周期&#xff1a;各個頁面的生命周期Vue 組件生命周期&#xff1a;Vue.js 原生的組件生命周期 這三種生命周期在不同場景下會按特定順…

MCU外設初始化:為什么參數配置必須優先于使能

在微控制器領域&#xff0c;初始化參數配置階段至關重要。此時&#xff0c;雖無電源驅動&#xff0c;但微控制器在使能信號到來前&#xff0c;借初始化參數配置這一精細步驟&#xff0c;開啟關鍵準備進程。初始化參數配置如同物理坐標錨定、邏輯指令部署、內在秩序預設&#xf…

AI一周事件(2025年8月6日-8月12日)

&#xff08;以下借助 DeepSeek-R1 & ChatGPT-5 輔助整理&#xff09; 一、AI 模型與算法進展 1. OpenAI 正式發布 GPT-5&#xff08;8月7日&#xff09; 事件&#xff1a;OpenAI 于 2025 年 8 月 7 日推出 GPT-5——其自稱擁有“PhD 級別”的智能&#xff0c;通過內置…