樹的子結構

文章目錄

  • 題目
  • 深搜
  • 深搜代碼
  • 廣搜
  • 廣搜代碼


題目

輸入兩棵二叉樹A和B,判斷B是不是A的子結構。(約定空樹不是任意一個樹的子結構)

B是A的子結構, 即 A中有出現和B相同的結構和節點值。

例如:
給定的樹 A:

在這里插入圖片描述
給定的樹 B:
在這里插入圖片描述
返回 true,因為 B 與 A 的一個子樹擁有相同的結構和節點值。

示例 1:

輸入:A = [1,2,3], B = [3,1]
輸出:false

示例 2:

輸入:A = [3,4,5,1,2], B = [4,1]
輸出:true

限制:

0 <= 節點個數 <= 10000


深搜

深搜思想主要是:

  1. 根據先序遍歷先尋找與B相等的節點nA
  2. 再判斷以nA為根節點的樹是否和B樹相吻合

算法流程:

函數 bool dfs(TreeNode* A, TreeNode* B);

1. 終止條件:

  1. 當節點 B 為空:說明樹 B 已匹配完成,因此返回 true
  2. 當節點 A 為空但節點 B 不為空:說明已經越過樹 A 葉子節點,即匹配失敗,返回 false ;
  3. 當節點 A 和 B 的值不同:說明匹配失敗,返回 false ;

2. 返回值:

  1. 判斷 A 和 B 的左子節點是否相等,即 dfs(A->left, B->left) ;
  2. 判斷 A 和 B 的右子節點是否相等,即 dfs(A->right, B->right) ;

函數 isSubStructure(TreeNode* A, TreeNode* B)

1. 特例處理:樹 A 為空樹 B 為空 時,直接返回 false
2. 返回值: 當 B 樹是 A 的子樹時,其必須滿足以下三個條件之一:

  1. A為根節點的樹包含 B 樹
  2. A的左子樹為根節點 的樹包含 B 樹
  3. A的右子樹為根節點 的樹包含 B 樹

上面 2. 3. 的實質就是在對樹 A 做先序遍歷

復雜度分析:

  1. 時間復雜度 O(MN) : 其中 M,N 分別為樹 A 和 樹 B 的節點數量;先序遍歷樹 A 占用 O(M) ,每次調用 dfs(A, B) 判斷占用 O(N) 。
  2. 空間復雜度 O(M) : 當樹 A 和樹 B 都退化為鏈表時,遞歸調用深度最大。當 M≤N 時,遍歷樹 A 與遞歸判斷的總遞歸深度為 M ;當 M>N 時,最差情況為遍歷至樹 A 葉子節點,此時總遞歸深度為 M。

深搜代碼

class Solution {public:bool dfs(TreeNode* A, TreeNode* B){if(B==nullptr){return true;}if(A==nullptr || A->val != B->val) return false;return dfs(A->left, B->left) && dfs(A->right, B->right);}bool isSubStructure(TreeNode* A, TreeNode* B) {if(A == nullptr || B == nullptr){return false;}bool res = false;if(A->val == B->val){res = dfs(A, B);}if(res){return res;}return isSubStructure(A->left, B) || isSubStructure(A->right, B);}
};

簡化版本:

class Solution {
public:bool dfs(TreeNode* A, TreeNode* B){if(B==nullptr) return true;if(A==nullptr || A->val != B->val) return false;return dfs(A->left, B->left) && dfs(A->right, B->right);}bool isSubStructure(TreeNode* A, TreeNode* B) {return  (A != NULL && B != NULL) && (dfs(A, B) || isSubStructure(A->left, B) || isSubStructure(A->right, B));}
};

廣搜

廣搜思想中也有 判定 nA為根節點 的樹與 B 樹是否吻合 的部分,因此其對應的函數和深搜中起到該作用的函數是一致的,無需更改。

不一樣的是 深搜用遞歸的的方法實現先序遍歷,而 廣搜用隊列來實現層序遍歷

也就是說,廣搜思想主要是:

  1. 根據層序遍歷先尋找與B相等的節點nA
  2. 再判斷以nA為根節點的樹是否和B樹相吻合

算法流程:

函數bool bfs(TreeNode* A, TreeNode* B); 和深搜部分一樣,就不再贅述了。

函數 isSubStructure(TreeNode* A, TreeNode* B);

1. 特例處理:樹 A 為空樹 B 為空 時,直接返回 false
2. 隊列實現層序遍歷:

  1. 先將 A 入隊
  2. 當隊列不為空時:
    1. 將隊列中的元素依次彈出,判斷其與 B 是否相等。
    2. 相等則判斷以nA為根節點的樹是否吻合 B 樹,吻合則直接返回。
    3. 不吻合則判斷彈出的元素左右子樹是否為空,不為空則入隊。

廣搜代碼

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution { 	
public:bool bfs(TreeNode* A, TreeNode* B){if(B==nullptr) return true;if(A==nullptr || A->val != B->val) return false;return bfs(A->left, B->left) && bfs(A->right, B->right);}bool isSubStructure(TreeNode* A, TreeNode* B) {if(A == nullptr || B == nullptr){return false;}bool res = false;queue<TreeNode*> q;q.push(A);while(!q.empty()){size_t qs = q.size();for(size_t i = 0; i < qs; i++){auto node = q.front();q.pop();if(node->val == B->val){res = bfs(node, B);}if(res){return res;}if(node->left) q.push(node->left);if(node->right) q.push(node->right);}}return res;}
};

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

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

相關文章

寫題過程中碰見的小問題

文章目錄和--vector二維vector的初始化數組中最大的數max_element()數組所有元素之和accumulate()vector數組去重對pair類型的vector排序對元素都為正整數的vector利用sort默認的升序排列進行降序排列一維數組轉二維數組size_t和int如何不用臨時變量交換兩個數?將類函數的形參…

LeetCode——二叉樹序列化與反序列化

文章目錄題目思路問題一問題二代碼實現題目 請實現兩個函數&#xff0c;分別用來序列化和反序列化二叉樹。 設計一個算法來實現二叉樹的序列化與反序列化。不限定序列 / 反序列化算法執行邏輯&#xff0c;你只需要保證一個二叉樹可以被序列化為一個字符串并且將這個字符串反序…

jsp中生成的驗證碼和存在session里面的驗證碼不一致的處理

今天在調試項目的時候發現&#xff0c;在提交表單的時候的驗證碼有問題&#xff0c;問題是這樣的&#xff1a;就是通過debug模式查看得知&#xff1a;jsp頁面生成的驗證碼和表單輸入的頁面輸入的一樣&#xff0c;但是到后臺執行的時候&#xff0c;你會發現他們是不一樣的&#…

求1~n這n個整數十進制表示中1出現的次數

文章目錄題目思路代碼復雜度分析題目 輸入一個整數 n &#xff0c;求1&#xff5e;n這n個整數的十進制表示中1出現的次數。 例如&#xff0c;輸入12&#xff0c;那么1&#xff5e;12這些整數中包含1 的數字有1、10、11和12。可得1一共出現了5次。 思路 將個位、十位……每位…

求數字序列中的第n位對應的數字

文章目錄題目思路代碼復雜度分析致謝題目 數字以0123456789101112131415…的格式序列化到一個字符序列中。在這個序列中&#xff0c;第5位&#xff08;從下標0開始計數&#xff09;是5&#xff0c;第13位是1&#xff0c;第19位是4&#xff0c;等等。 請寫一個函數&#xff0c…

一學就廢的歸并排序

文章目錄其他與排序有關的文章原理代碼實現復雜度分析其他與排序有關的文章 一學就廢的三種簡單排序【冒泡、插入、選擇】 原理 歸并排序&#xff08;Merge sort&#xff09;&#xff1a; 歸并排序對元素 遞歸地 進行 逐層折半分組&#xff0c;然后從最小分組開始&#xff0c…

神奇的x -x,Lowbit函數的實現方式!

文章目錄-xx & -x&#xff0c;當x為偶數時x & -x&#xff0c;當x為奇數時x&-x 的實際用途-x -x 在二進制里表示對 x 的二進制按位取反(~x)之后再加 1 &#xff0c;即 -x ~x1x & -x&#xff0c;當x為偶數時 在執行 x & -x 時&#xff0c;若 x 為偶數&am…

JAVA實現把指定文件夾下的所有文件壓縮成zip包

1.代碼如下&#xff1a; package cn.gov.csrc.base.util;import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import…

樹狀數組的相關知識 及 求逆序對的運用

文章目錄樹狀數組概念前綴和和區間和樹狀數組原理區間和——單點更新前綴和——區間查詢完整代碼離散化sort函數unique函數去重erase函數僅保留不重復元素通過樹狀數組求逆序對樹狀數組概念 樹狀數組又名二叉索引樹&#xff0c;其查詢與插入的復雜度都為 O(logN)&#xff0c;其…

二叉搜索樹相關知識及應用操作

文章目錄概念查找二叉搜索樹的第k大節點概念 二叉查找樹&#xff08;Binary Search Tree&#xff09;&#xff0c;&#xff08;又名&#xff1a;二叉搜索樹&#xff0c;二叉排序樹&#xff09;——它或者是一棵空樹&#xff0c;或者是具有下列性質的二叉樹&#xff1a; 若它的…

二叉樹相關知識及求深度的代碼實現

文章目錄樹二叉樹滿二叉樹和完全二叉樹二叉樹的性質代碼實現求二叉樹的深度樹 樹是一種非線性的數據結構&#xff0c;它是由n個有限結點組成一個具有層次關系的集合。 樹的相關名詞&#xff1a; 根節點&#xff1a;沒有前驅結點的結點。父節點&#xff0c;子節點&#xff1a…

平衡樹相關知識及如何判斷一棵樹是否平衡

文章目錄概念代碼實現判斷一棵二叉樹是否為平衡樹概念 平衡樹(Balance Tree&#xff0c;BT) 指的是&#xff0c;任意節點的子樹的高度差都小于等于1。 常見的符合平衡樹的有&#xff1a; B樹&#xff08;多路平衡搜索樹&#xff09;AVL樹&#xff08;二叉平衡搜索樹&#xf…

大端小端存儲模式詳解及判斷方法

文章目錄大小端模式的概念兩種模式出現原因兩種模式的優劣大小端的應用情景判斷機器的字節序大小端模式的概念 當我們查看數據在內存中的存儲情況時&#xff0c;我們經常會發現一個很奇怪的現象&#xff0c;什么現象呢&#xff1f; int main() {int i 12;return 0; }數據在內…

Linux 內存管理 | 物理內存、內存碎片、伙伴系統、SLAB分配器

文章目錄物理內存物理內存分配外部碎片內部碎片伙伴系統(buddy system)slab分配器物理內存 在Linux中&#xff0c;內核將物理內存劃分為三個區域。 在解釋DMA內存區域之前解釋一下什么是DMA&#xff1a; DMA&#xff08;直接存儲器訪問&#xff09; 使用物理地址訪問內存&am…

Linux 內存管理 | 虛擬內存管理:虛擬內存空間、虛擬內存分配

文章目錄虛擬地址空間用戶空間內核空間用戶空間內存分配malloc內核空間內存分配kmallocvmalloc虛擬地址空間 在早期的計算機中&#xff0c;程序是直接運行在物理內存上的&#xff0c;而直接使用物理內存&#xff0c;通常都會面臨以下幾種問題&#xff1a; 內存缺乏訪問控制&a…

Linux | 編譯原理、gcc的命令參數、自動化構建工具 make/Makefile

文章目錄編譯原理預處理編譯匯編鏈接gcc的常用命令參數make 和 Makefile 的概念make的運行通配符自動化變量偽目標.PHONE:【命令】編譯原理 在解釋 makefile 前&#xff0c;首先解釋一下 .c 文件變成 .exe 文件要經過的四個步驟——預處理、編譯、匯編和鏈接&#xff08;參考來…

全排列變種:限定 排列的差值范圍 及 排列中的元素個數

文章目錄題目描述思路代碼實現題目描述 詳細描述&#xff1a;字節跳動2019春招研發部分編程題——萬萬沒想到之抓捕孔連順 輸入描述&#xff1a; 第一行包含空格分隔的兩個數字 N和D(1?≤?N?≤?1000000; 1?≤?D?≤?1000000) 第二行包含N個整數&#xff08;取值區間為…

Linux | 進程概念、進程狀態(僵尸進程、孤兒進程、守護進程)、進程地址空間

文章目錄進程和程序操作系統如何控制和調度程序進程控制塊–PCB子進程進程狀態僵尸進程孤兒進程守護進程&#xff08;精靈進程&#xff09;進程地址空間引言頁表進程和程序 程序&#xff1a; 一系列有序的指令集合&#xff08;就是我們寫的代碼&#xff09;。進程&#xff1a;…

Linux 進程控制 :進程創建,進程終止,進程等待,程序替換

文章目錄進程創建進程等待程序替換進程終止進程創建 fork函數&#xff1a; 操作系統提供的創建新進程的方法&#xff0c;父進程通過調用 fork函數 創建一個子進程&#xff0c;父子進程代碼共享&#xff0c;數據獨有。 當調用 fork函數 時&#xff0c;通過 寫時拷貝技術 來拷貝…

Linux 內存管理 | 連續分配方式 和 離散分配方式

文章目錄前言連續分配單一連續分配分區式分配固定分區分配動態分區分配可重定位分區分配離散分配分段分頁多級頁表快表(TLB)段頁式Linux前言 Linux 內存管理 | 虛擬內存管理&#xff1a;虛擬內存空間、虛擬內存分配 Linux 內存管理 | 物理內存、內存碎片、伙伴系統、SLAB分配器…