二叉樹子樹判斷:從遞歸到迭代的全方位解析

一、題目解析

題目描述

給定兩棵二叉樹rootsubRoot,判斷root中是否存在一棵子樹,其結構和節點值與subRoot完全相同。

示例說明

  • 示例1
    root = [3,4,5,1,2]subRoot = [4,1,2]
    返回true,因為root的左子樹與subRoot完全相同。

  • 示例2
    root = [3,4,5,1,2,null,null,null,null,0]subRoot = [4,1,2]
    返回false,雖然root存在節點值為4、1、2的路徑,但結構與subRoot不同。

核心難點

  1. 如何高效遍歷主樹,找到可能與子樹匹配的起始節點?
  2. 如何精確判斷兩棵樹是否完全相同,避免結構或值的差異?

二、遞歸解法:深度優先搜索

核心思路

  1. 遞歸遍歷主樹:對主樹的每個節點,檢查以該節點為根的子樹是否與目標子樹相同。
  2. 遞歸判斷子樹是否相同:同時遍歷兩棵樹的對應節點,確保結構和值完全一致。

代碼實現

class Solution {public boolean isSubtree(TreeNode root, TreeNode subRoot) {return bfs(root,subRoot);}public boolean bfs(TreeNode root, TreeNode subRoot){if(root == null){return false;}return check(root,subRoot) || bfs(root.left,subRoot) || bfs(root.right,subRoot);}public boolean check(TreeNode root, TreeNode subRoot){if(root == null && subRoot == null){return true;}if(root == null || subRoot == null || root.val != subRoot.val){return false;}return check(root.left,subRoot.left) && check(root.right,subRoot.right);}
}

代碼解析

  1. 主方法 isSubtree
    調用bfs方法開始遞歸遍歷主樹。

  2. 遞歸遍歷方法 bfs

    • 終止條件:若主樹為空,返回false
    • 檢查當前節點:調用check方法判斷以當前節點為根的子樹是否與目標子樹相同。
    • 遞歸搜索左右子樹:只要在任一子樹中找到匹配,立即返回true
  3. 子樹比較方法 check

    • 終止條件:若兩節點均為空,返回true;若僅一者為空或值不同,返回false
    • 遞歸比較:遞歸檢查左右子樹是否完全相同。

三、迭代解法:雙端隊列層序遍歷

核心思路

  1. 層序遍歷主樹:使用雙端隊列按層遍歷主樹的每個節點。
  2. 檢查子樹是否相同:對每個節點,使用另一個雙端隊列同步比較其與目標子樹的結構和值。

代碼實現

class Solution {public boolean isSubtree(TreeNode root, TreeNode subRoot) {Deque<TreeNode> cur = new LinkedList<>();if (subRoot == null) return true;  if (root == null) return false;   TreeNode tempRoot = root;cur.offer(tempRoot);while(!cur.isEmpty()){tempRoot = cur.pollFirst();if(isSameTree(tempRoot,subRoot)){return true;}if(tempRoot.left != null){cur.offerFirst(tempRoot.left);}if(tempRoot.right != null){cur.offerFirst(tempRoot.right);}}return false;}public boolean isSameTree(TreeNode root, TreeNode subRoot) {Deque<TreeNode> cur = new LinkedList<>();if (root == null && subRoot == null) {return true;}TreeNode tempRoot = root;TreeNode tempSubRoot = subRoot;cur.offerFirst(tempRoot);cur.offerLast(tempSubRoot);while (!cur.isEmpty()) {tempRoot = cur.pollFirst();tempSubRoot = cur.pollLast();if (tempRoot == null && tempSubRoot == null) {continue;}if (tempRoot == null || tempSubRoot == null || tempSubRoot.val != tempRoot.val) {return false;}cur.offerFirst(tempRoot.left);cur.offerFirst(tempRoot.right);cur.offerLast(tempSubRoot.left);cur.offerLast(tempSubRoot.right);}return true;}
}

代碼解析

  1. 主方法 isSubtree

    • 初始化隊列:將主樹根節點入隊。
    • 層序遍歷:每次從隊列取出節點,調用isSameTree檢查是否匹配。
    • 擴展隊列:將當前節點的左右子節點入隊,繼續遍歷。
  2. 子樹比較方法 isSameTree

    • 雙隊列同步遍歷:使用雙端隊列分別存儲主樹和子樹的節點。
    • 節點比較:每次從隊列取出兩個節點,檢查是否結構和值相同,并將其子節點入隊。
    • 入隊策略:主樹節點從隊首入隊,子樹節點從隊尾入隊,確保對應節點同步比較。

四、尋找匹配節點的關鍵邏輯

遞歸法

  • 遍歷策略:采用前序遍歷(根→左→右),確保每個節點都被檢查。
  • 匹配條件:當且僅當當前節點及其所有后代與子樹完全相同時,返回true

迭代法

  • 遍歷策略:層序遍歷(BFS),按層檢查每個節點。
  • 匹配條件:使用雙隊列同步比較,確保每個對應節點的結構和值一致。

對比分析

方法遍歷方式時間復雜度空間復雜度適用場景
遞歸法深度優先(DFS)O(m*n)O(max(h1,h2))樹較淺,遞歸棧空間充足
迭代法廣度優先(BFS)O(m*n)O(max(w1,w2))避免遞歸棧溢出

其中,m和n分別為主樹和子樹的節點數,h為樹的高度,w為樹的最大寬度。

五、常見誤區與邊界條件

1. 空樹處理

  • 子樹為空:題目規定空樹是任何樹的子樹,因此直接返回true
  • 主樹為空:若主樹為空,僅當子樹也為空時返回true,否則返回false

2. 結構與值的雙重匹配

  • 示例:主樹[1,1],子樹[1]
    雖然主樹存在節點值為1的子樹,但結構不同(主樹有兩個節點),因此返回false

3. 部分路徑匹配問題

  • 示例:主樹[3,4,5,1,2,null,null,null,null,0],子樹[4,1,2]
    主樹的左子樹路徑為4→1→2,但2的右子節點存在0,與子樹結構不符,故返回false

六、總結

核心算法思路

  1. 遍歷主樹:遞歸或迭代方式遍歷每個節點。
  2. 檢查子樹:對每個節點,遞歸或迭代比較其與目標子樹的結構和值。

代碼優化建議

  1. 遞歸法:簡潔直觀,但可能導致棧溢出,適用于樹高較小的場景。
  2. 迭代法:避免棧溢出,但代碼復雜度較高,需維護雙隊列同步遍歷。

關鍵技巧

  • 雙隊列同步遍歷:確保主樹和子樹的對應節點被正確比較。
  • 層序遍歷:通過隊列按層處理節點,適合大規模數據。

理解這兩種解法的核心邏輯后,可靈活應對類似的樹結構匹配問題,如判斷樹的子結構、樹的鏡像等變體。

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

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

相關文章

Springboot 異步場景 使用注解 @Async 及 自定義線程池分模塊使用

目錄 前言一、Springboot項目如何開啟異步&#xff1f;二、存在的問題三、自定義線程池四、自定義線程池使用五、阻塞隊列和拒絕策略 前言 當開發中遇到不影響主流程任務時&#xff0c;使用異步去處理。 如有以下場景&#xff1a; 1、業務需要生成一個季度的數據進行員工排名&…

【GNN筆記】Signed Graph Convolutional Network(12)【未完】

視頻鏈接&#xff1a;《圖神經網絡》 Signed Graph Convolutional Network 之前介紹的GNN模型主要集中在無符號的網絡&#xff08;或僅由正鏈接組成的圖&#xff09;上&#xff0c;符號 圖帶來的挑戰&#xff0c;主要集中在于 否定鏈接&#xff0c;與正鏈接相比&#xff0c;它不…

米勒電容補償的理解

米勒電容補償是使運放放大器穩定的重要手法&#xff0c;可以使兩級運放的兩個極點分離&#xff0c;從而可以得到更好的相位裕度。 Miller 電容補償的本質是增加一條通路流電流&#xff0c;流電流才是miller效應的本質。給定一個相同的輸入&#xff0c;Miller 電容吃掉的電流比…

CVE-2017-8046 漏洞深度分析

漏洞概述 CVE-2017-8046 是 Spring Data REST 框架中的一個高危遠程代碼執行漏洞&#xff0c;影響版本包括 Spring Data REST < 2.5.12、2.6.7、3.0 RC3 及關聯的 Spring Boot 和 Spring Data 舊版本。攻擊者通過構造包含惡意 SpEL&#xff08;Spring Expression Language&…

qt文本邊框設置

// 計算文本的大致尺寸 QFontMetrics fm(textEditor->font()); QRect textRect fm.boundingRect(textItem->toPlainText()); // 設置編輯框大小&#xff0c;增加一些邊距 const int margin 10; textEditor->setGeometry( center.x() - textRect.width()/2 - margin,…

Java 與 面向對象編程(OOP)

Java 是典型的純面向對象編程語言&#xff08;Pure Object-Oriented Language&#xff09;&#xff0c;其設計嚴格遵循面向對象&#xff08;OOP&#xff09;的核心原則。以下是具體分析&#xff1a; 1. Java 的面向對象核心特性 (1) 一切皆對象 Java 中幾乎所有的操作都圍繞…

導出導入Excel文件(詳解-基于EasyExcel)

前言&#xff1a; 近期由于工作的需要&#xff0c;根據需求需要導出導入Excel模板。于是自學了一下下&#xff0c;在此記錄并分享&#xff01;&#xff01; EasyExcel&#xff1a; 首先我要在這里非常感謝阿里的大佬們&#xff01;封裝這么好用的Excel相關的API&#xff0c;真…

python版本管理工具-pyenv輕松切換多個Python版本

在使用python環境開發時&#xff0c;相信肯定被使用版本所煩惱&#xff0c;在用第三方庫時依賴兼容的python版本不一樣&#xff0c;有沒有一個能同時安裝多個python并能自由切換的工具呢&#xff0c;那就是pyenv&#xff0c;讓你可以輕松切換多個Python 版本。 pyenv是什么 p…

Elasticsearch 索引副本數

作者&#xff1a;來自 Elastic Kofi Bartlett 解釋如何配置 number_of_replicas、它的影響以及最佳實踐。 更多閱讀&#xff1a;Elasticsearch 中的一些重要概念: cluster, node, index, document, shards 及 replica 想獲得 Elastic 認證&#xff1f;查看下一期 Elasticsearc…

AXI4總線協議 ------ AXI_LITE協議

一、AXI 相關知識介紹 https://download.csdn.net/download/mvpkuku/90841873 AXI_LITE 選出部分重點&#xff0c;詳細文檔見上面鏈接。 1.AXI4 協議類型 2.握手機制 二、AXI_LITE 協議的實現 1. AXI_LITE 通道及各通道端口功能介紹 2.實現思路及框架 2.1 總體框架 2.2 …

idea運行

各種小kips Linuxidea上傳 Linux 部署流程 1、先在idea打好jar包&#xff0c;clean之后install 2、在Linux目錄下&#xff0c;找到對應項目目錄&#xff0c;把原來的jar包放在bak文件夾里面 3、殺死上一次jar包的pid ps -ef|grep cliaidata.jar kill pid 4、再進行上傳新的jar…

FPGA: XILINX Kintex 7系列器件的架構

本文將詳細介紹Kintex-7系列FPGA器件的架構。以下內容將涵蓋Kintex-7的核心架構特性、主要組成部分以及關鍵技術&#xff0c;盡量全面且結構化&#xff0c;同時用簡潔的語言確保清晰易懂。 Kintex-7系列FPGA架構概述 Kintex-7是Xilinx 7系列FPGA中的中高端產品線&#xff0c;基…

【LLM】大模型落地應用的技術 ——— 推理訓練 MOE,AI搜索 RAG,AI Agent MCP

【LLM】大模型落地應用的技術 ——— 推理訓練MOE&#xff0c;AI搜索RAG&#xff0c;AI Agent MCP 文章目錄 1、推理訓練 MOE2、AI搜索 RAG3、AI Agent MCP 1、推理訓練 MOE MoE 是模型架構革新&#xff0c;解決了算力瓶頸。原理是多個專家模型聯合計算。 推理訓練MoE&#xff…

10 web 自動化之 yaml 數據/日志/截圖

文章目錄 一、yaml 數據獲取二、日志獲取三、截圖 一、yaml 數據獲取 需要安裝 PyYAML 庫 import yaml import os from TestPOM.common import dir_config as Dir import jsonpathclass Data:def __init__(self,keyNone,file_name"test_datas.yaml"):file_path os…

中exec()函數因$imagePath參數導致的命令注入漏洞

exec(zbarimg -q . $imagePath, $barcodeList, $returnVar); 針對PHP中exec()函數因$imagePath參數導致的命令注入漏洞&#xff0c;以下是安全解決方案和最佳實踐&#xff1a; 一、漏洞原理分析 直接拼接用戶輸入$imagePath到系統命令中&#xff0c;攻擊者可通過注入特殊字…

this.$set的用法-響應式數據更新

目錄 一、核心作用 三、使用場景與示例 1. 給對象添加新屬性 四、與 Vue.set 的關系 五、底層原理 六、Vue 3 的替代方案 七、最佳實踐 八、常見問題 Q&#xff1a;為什么修改嵌套對象屬性不需要 $set&#xff1f; Q&#xff1a;$set 和 $forceUpdate 的區別&#xf…

【生成式AI文本生成實戰】DeepSeek系列應用深度解析

目錄 &#x1f31f; 前言&#x1f3d7;? 技術背景與價值&#x1fa79; 當前技術痛點&#x1f6e0;? 解決方案概述&#x1f465; 目標讀者說明 &#x1f9e0; 一、技術原理剖析&#x1f4ca; 核心概念圖解&#x1f4a1; 核心作用講解&#x1f527; 關鍵技術模塊說明?? 技術選…

c/c++的opencv的圖像預處理講解

OpenCV 圖像預處理核心技術詳解 (C/C) 圖像預處理是計算機視覺任務中至關重要的一步。原始圖像往往受到噪聲、光照不均、尺寸不一等多種因素的影響&#xff0c;直接用于后續分析&#xff08;如特征提取、目標檢測、機器學習模型訓練等&#xff09;可能會導致性能下降或結果不準…

使用 Docker 部署 React + Nginx 應用教程

目錄 1. 創建react項目結構2. 創建 .dockerignore3. 創建 Dockerfile4. 創建 nginx.conf5. 構建和運行6. 常用命令 1. 創建react項目結構 2. 創建 .dockerignore # 依賴目錄 node_modules npm-debug.log# 構建輸出 dist build# 開發環境文件 .git .gitignore .env .env.local …

Java 流(Stream)API

一、理論說明 1. 流的定義 Java 流&#xff08;Stream&#xff09;是 Java 8 引入的新特性&#xff0c;用于對集合&#xff08;如 List、Set&#xff09;或數組進行高效的聚合操作&#xff08;如過濾、映射、排序&#xff09;和并行處理。流不存儲數據&#xff0c;而是按需計…