衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

這么簡單的二叉樹算法都不會(huì)?

算法與數(shù)據(jù)結(jié)構(gòu) ? 來源:碼農(nóng)的荒島求生 ? 2023-08-29 11:19 ? 次閱讀

要求是這樣的:給定兩顆二叉樹A和B,判斷B是否是A的子樹。

在下面這個(gè)例子中可以看到B是A的子樹。

82e86654-40d6-11ee-a2ef-92fbcf53809c.png

想一想該怎樣解決這個(gè)問題呢?

如果B是A的一顆子樹,那么B一定和A的一個(gè)顆子樹完全一樣,因此我們可以實(shí)現(xiàn)一個(gè)函數(shù)isSame來判斷兩顆二叉樹是否完全相同,這個(gè)函數(shù)非常容易實(shí)現(xiàn):

bool isSame(TreeNode* a, TreeNode* b) {
    if (a == nullptr && b == nullptr) return true;
    else if (a == nullptr || b == nullptr) return false;
    else return a->val == b->val && isSame(a->left, b->left) && isSame(a->right, b->right);
}
只需要三行代碼就能搞定,該函數(shù)非常簡單:

如果二叉樹a和b都為空,那么顯然返回true

否則如果a為空或者b為空,那么這兩棵樹顯然不相同,返回false

如果不滿足條件1和2,那么如果a和b根節(jié)點(diǎn)的值相同并且其左右子樹都一樣,那么二叉樹a和b是相同的二叉樹,返回true

有了isSame函數(shù)剩下的就簡單啦,我們只需要在遍歷二叉樹a時(shí)不斷的調(diào)用isSame函數(shù)判斷是否b是a的子樹相同:

8302fab4-40d6-11ee-a2ef-92fbcf53809c.png

同樣的,只需要三行代碼就能搞定:

bool isSubtree(TreeNode* root, TreeNode* subRoot) {
    if (root == nullptr && subRoot == nullptr) return true;
    else if (root == nullptr || subRoot == nullptr) return false;
    else return isSame(root, subRoot) || isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}
代碼非常簡單,就是二叉樹的普通遍歷。

有的同學(xué)可能已經(jīng)發(fā)現(xiàn)了,這種算法的實(shí)際上不太高效,原因就在于對于二叉樹a上的每個(gè)節(jié)點(diǎn)我們都需要調(diào)用一遍isSame函數(shù),如果二叉樹a的節(jié)點(diǎn)數(shù)為M、二叉樹b的節(jié)點(diǎn)數(shù)為N,那么該算法的時(shí)間復(fù)雜度為O(M*N)。

我們一定對二叉樹a中的每個(gè)節(jié)點(diǎn)都調(diào)用一遍isSame函數(shù)嗎?

實(shí)際上這并不是必須的。

要能想出更高效的算法,你需要理解編碼的概念。

熟悉md5的同學(xué)都知道,我們可以對任何一個(gè)文件計(jì)算出md5值,md5就是一串?dāng)?shù)字,就好像指紋一樣,只需要兩個(gè)文件完全一樣,那么這兩個(gè)文件的md5就完全一樣,因此我們可以通過比較md5來確認(rèn)兩個(gè)文件是否完全一樣,在linux下用md5sum命令可以計(jì)算一個(gè)文件的md5值:
$ md5sum a.c
6004b6a21b274b405a2bd1f1c75a93c7  a.c
同樣的,我們也可以對二叉樹計(jì)算“md5”值。

怎么計(jì)算呢?

實(shí)際上非常簡單。

我們只需要在二叉樹的前序遍歷過程中輸出“遍歷軌跡”,那么就能將一顆二叉樹序列化成一個(gè)字符串

如果二叉樹b是a的子樹,那么必然二叉樹b序列化的后的字符串是a序列化后的字符串的子串。

這樣通過編碼,我們將二叉樹子樹的判斷問題轉(zhuǎn)化為了字符串的子串匹配問題,而字符串匹配問題可以通過經(jīng)典的KMP算法解決。

83219c08-40d6-11ee-a2ef-92fbcf53809c.png

將二叉樹序列化為字符串的函數(shù)也很簡單:
void serialize(TreeNode* root, string& str) {
    if (root == nullptr) {
        str = str + "#";
    } else {
        str = str  + "," + to_string(root->val);


        serialize(root->left, str);
        serialize(root->right, str);
    }
}
可以看到,該代碼實(shí)際上還是二叉樹的遍歷。

既然我們可以將二叉樹序列化了字符串,那么接下來就簡單啦:
bool isSubtree(TreeNode* root, TreeNode* subRoot) {
    string a, b;
    serialize(root, a);
    serialize(subRoot, b);
    return a.find(b)!=string::npos;
}
將二叉樹序列化為字符串后只需要判斷字符串b是否是字符串a(chǎn)的子串即可。

從這個(gè)題目上我們可以看到信息編碼的重要作用,這也是一種非常值得掌握的思想,有時(shí)對解決問題有四兩撥千斤的效果






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 編碼器
    +關(guān)注

    關(guān)注

    45

    文章

    3669

    瀏覽量

    135247
  • Linux系統(tǒng)
    +關(guān)注

    關(guān)注

    4

    文章

    595

    瀏覽量

    27510
  • 字符串
    +關(guān)注

    關(guān)注

    1

    文章

    585

    瀏覽量

    20603
  • 二叉樹
    +關(guān)注

    關(guān)注

    0

    文章

    74

    瀏覽量

    12376

原文標(biāo)題:面試官:這么簡單的二叉樹算法都不會(huì)?

文章出處:【微信號:TheAlgorithm,微信公眾號:算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    二叉樹算法在單總線技術(shù)中的應(yīng)用

    介紹了單總線技術(shù)和二叉樹算法。單總線技術(shù)可以將地址線、數(shù)據(jù)線和控制線合成一根線,并允許在這根線上掛接多個(gè)單總線器件。提出了用二叉樹算法搜索單總線器件注冊碼,并
    發(fā)表于 03-16 09:38 ?20次下載

    基于二叉樹分解的自適應(yīng)防碰撞算法

    該文提出了一種基于二叉樹分解的自適應(yīng)防碰撞算法。新算法利用標(biāo)簽EPC 的唯一性,通過時(shí)隙分配估計(jì)標(biāo)簽的分布情況,對發(fā)生碰撞的時(shí)隙進(jìn)行二叉樹搜索,從而將一個(gè)龐大且復(fù)雜
    發(fā)表于 11-17 14:09 ?21次下載

    基于二叉樹的時(shí)序電路測試序列設(shè)計(jì)

    為了實(shí)現(xiàn)時(shí)序電路狀態(tài)驗(yàn)證和故障檢測,需要事先設(shè)計(jì)一個(gè)輸入測試序列。基于二叉樹節(jié)點(diǎn)和樹枝的特性,建立時(shí)序電路狀態(tài)二叉樹,按照電路二叉樹節(jié)點(diǎn)(狀態(tài))與樹枝(輸入)的層次邏輯
    發(fā)表于 07-12 13:57 ?0次下載
    基于<b class='flag-5'>二叉樹</b>的時(shí)序電路測試序列設(shè)計(jì)

    二叉樹層次遍歷算法的驗(yàn)證

    實(shí)現(xiàn)二叉樹的層次遍歷算法,并對用”A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))”創(chuàng)建的二叉樹進(jìn)行測試。
    發(fā)表于 11-28 01:05 ?2119次閱讀
    <b class='flag-5'>二叉樹</b>層次遍歷<b class='flag-5'>算法</b>的驗(yàn)證

    二叉樹,一種基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)類型

    然后我們再定義一棵深度也為 3 的二叉樹,該二叉樹的 n 個(gè)結(jié)點(diǎn)(n≤7),當(dāng)從 1 到 n 的每個(gè)結(jié)點(diǎn)都與上圖中的編號結(jié)點(diǎn)一一對應(yīng)時(shí),這二叉樹就稱為完全二叉樹
    的頭像 發(fā)表于 04-13 10:48 ?4413次閱讀
    <b class='flag-5'>二叉樹</b>,一種基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)類型

    詳解電源二叉樹到底是什么

    作為數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ),分很多種,像 AVL 、紅黑二叉搜索....今天我想分享的是關(guān)于二叉樹
    的頭像 發(fā)表于 06-06 15:05 ?1w次閱讀
    詳解電源<b class='flag-5'>二叉樹</b>到底是什么

    二叉樹操作的相關(guān)知識(shí)和代碼詳解

    是數(shù)據(jù)結(jié)構(gòu)中的重中之重,尤其以各類二叉樹為學(xué)習(xí)的難點(diǎn)。在面試環(huán)節(jié)中,二叉樹也是必考的模塊。本文主要講二叉樹操作的相關(guān)知識(shí),梳理面試常考的內(nèi)容。請大家跟隨小編一起來復(fù)習(xí)吧。 本篇針對面
    的頭像 發(fā)表于 12-12 11:04 ?2089次閱讀
    <b class='flag-5'>二叉樹</b>操作的相關(guān)知識(shí)和代碼詳解

    二叉樹的前序遍歷非遞歸實(shí)現(xiàn)

    我們之前說了二叉樹基礎(chǔ)及二叉的幾種遍歷方式及練習(xí)題,今天我們來看一下二叉樹的前序遍歷非遞歸實(shí)現(xiàn)。 前序遍歷的順序是, 對于中的某節(jié)點(diǎn),先遍歷該節(jié)點(diǎn),然后再遍歷其左子樹,最后遍歷其右子
    的頭像 發(fā)表于 05-28 13:59 ?2000次閱讀

    數(shù)據(jù)結(jié)構(gòu)與算法分析中的二叉樹與堆有關(guān)知識(shí)匯總

    該資料包括數(shù)據(jù)結(jié)構(gòu)與算法分析中的二叉樹與堆有關(guān)的一些知識(shí)
    發(fā)表于 11-03 09:37 ?0次下載

    C語言數(shù)據(jù)結(jié)構(gòu):什么是二叉樹

    完全二叉樹:完全二叉樹是效率很高的數(shù)據(jù)結(jié)構(gòu)。對于深度為K,有n個(gè)節(jié)點(diǎn)的二叉樹,當(dāng)且僅當(dāng)每一個(gè)節(jié)點(diǎn)都與深度為K的滿二叉樹中編號從1至n的節(jié)點(diǎn)一一對應(yīng)時(shí),稱為完全
    的頭像 發(fā)表于 04-21 16:20 ?2699次閱讀

    怎么就能構(gòu)造成二叉樹呢?

    一直跟著公眾號學(xué)算法的錄友 應(yīng)該知道,我在二叉樹:構(gòu)造二叉樹登場!,已經(jīng)講過,只有 中序與后序 和 中序和前序 可以確定一顆唯一的二叉樹。前序和后序是不能確定唯一的
    的頭像 發(fā)表于 07-14 11:20 ?1655次閱讀

    使用C語言代碼實(shí)現(xiàn)平衡二叉樹

    這篇博客主要總結(jié)平衡二叉樹,所以,二叉排序樹知識(shí)不會(huì)提及,但是會(huì)用到。
    的頭像 發(fā)表于 09-21 11:00 ?1154次閱讀

    二叉樹的代碼實(shí)現(xiàn)

    二叉樹的主要操作有遍歷,例如有先序遍歷、中序遍歷、后序遍歷。在遍歷之前,就是創(chuàng)建一棵二叉樹,當(dāng)然,還需要有刪除二叉樹算法
    的頭像 發(fā)表于 01-18 10:41 ?1277次閱讀
    <b class='flag-5'>二叉樹</b>的代碼實(shí)現(xiàn)

    C++構(gòu)建并復(fù)制二叉樹

    使用C++構(gòu)建一個(gè)二叉樹并復(fù)制、輸出。
    的頭像 發(fā)表于 01-10 15:17 ?1079次閱讀
    C++構(gòu)建并復(fù)制<b class='flag-5'>二叉樹</b>

    C++自定義二叉樹并輸出二叉樹圖形

    使用C++構(gòu)建一個(gè)二叉樹并輸出。
    的頭像 發(fā)表于 01-10 16:29 ?1810次閱讀
    C++自定義<b class='flag-5'>二叉樹</b>并輸出<b class='flag-5'>二叉樹</b>圖形
    百家乐官网桌布动物| 百家乐官网真人游戏网上投注| 利都百家乐国际赌场娱乐网规则 | 玉林市| 百家乐画面方法| 百家乐单跳双跳| 玩百家乐官网凤凰娱乐城| 大发888 王博| 百家乐注码技术打法| 乐中百家乐官网的玩法技巧和规则 | 网络真人赌博| 威尼斯人娱乐网注册网址| 百家乐三号的赢法| 百家乐官网讯特| 九龙娱乐| 威尼斯人娱乐城首存优惠| 百家乐游戏平台架设| 沙龙百家乐官网娱乐网| 冷水江市| 大发888怎么找不到了| 百家乐游戏网上投注| 沁水县| 悠哉棋牌游戏大厅| 百家乐什么方法容易赢| 互博百家乐官网的玩法技巧和规则| 新世纪百家乐官网现金网| 狮威娱乐| 大发888官方 黄埔网| 唐人街百家乐的玩法技巧和规则| 百家乐网投开户| 百家乐官网娱乐平台真钱游戏| 真人百家乐官网现金游戏| 星河娱乐| 大发888真钱账户注册| 有钱人百家乐的玩法技巧和规则 | 百家乐官网币| 百家乐官网游戏合法吗| 龙博娱乐| 大发888 ber娱乐场下载| 大发888娱乐城维护| 高尔夫百家乐的玩法技巧和规则 |