吴忠躺衫网络科技有限公司

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

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

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

如何修剪二叉搜索樹

算法與數(shù)據(jù)結(jié)構(gòu) ? 來源:代碼隨想錄 ? 作者:程序員Carl ? 2021-10-11 14:16 ? 次閱讀

如果不對(duì)遞歸有深刻的理解,本題有點(diǎn)難。單純移除一個(gè)節(jié)點(diǎn)那還不夠,要修剪!

669. 修剪二叉搜索樹

給定一個(gè)二叉搜索樹,同時(shí)給定最小邊界L 和最大邊界 R。通過修剪二叉搜索樹,使得所有節(jié)點(diǎn)的值在[L, R]中 (R>=L) 。你可能需要改變樹的根節(jié)點(diǎn),所以結(jié)果應(yīng)當(dāng)返回修剪好的二叉搜索樹的新的根節(jié)點(diǎn)。

思路

相信看到這道題目大家都感覺是一道簡(jiǎn)單題(事實(shí)上leetcode上也標(biāo)明是簡(jiǎn)單)。

但還真的不簡(jiǎn)單!

遞歸法

直接想法就是:遞歸處理,然后遇到root->val < low || root->val > high的時(shí)候直接return NULL,一波修改,趕緊利落。

不難寫出如下代碼:

classSolution{
public:
TreeNode*trimBST(TreeNode*root,intlow,inthigh){
if(root==nullptr||root->valval>high)returnnullptr;
root->left=trimBST(root->left,low,high);
root->right=trimBST(root->right,low,high);
returnroot;
}
};

然而[1, 3]區(qū)間在二叉搜索樹的中可不是單純的節(jié)點(diǎn)3和左孩子節(jié)點(diǎn)0就決定的,還要考慮節(jié)點(diǎn)0的右子樹

所以以上的代碼是不可行的!

從圖中可以看出需要重構(gòu)二叉樹,想想是不是本題就有點(diǎn)復(fù)雜了。

其實(shí)不用重構(gòu)那么復(fù)雜。

在上圖中我們發(fā)現(xiàn)節(jié)點(diǎn)0并不符合區(qū)間要求,那么將節(jié)點(diǎn)0的右孩子 節(jié)點(diǎn)2 直接賦給 節(jié)點(diǎn)3的左孩子就可以了(就是把節(jié)點(diǎn)0從二叉樹中移除)

理解了最關(guān)鍵部分了我們?cè)谶f歸三部曲:

這里我們?yōu)槭裁葱枰祷刂的兀?/p>

因?yàn)槭且闅v整棵樹,做修改,其實(shí)不需要返回值也可以,我們也可以完成修剪(其實(shí)就是從二叉樹中移除節(jié)點(diǎn))的操作。

但是有返回值,更方便,可以通過遞歸函數(shù)的返回值來移除節(jié)點(diǎn)。

這樣的做法在二叉樹:搜索樹中的插入操作二叉樹:搜索樹中的刪除操作中大家已經(jīng)了解過了。

代碼如下:

TreeNode*trimBST(TreeNode*root,intlow,inthigh)
  • 確定終止條件

修剪的操作并不是在終止條件上進(jìn)行的,所以就是遇到空節(jié)點(diǎn)返回就可以了。

if(root==nullptr)returnnullptr;
  • 確定單層遞歸的邏輯

如果root(當(dāng)前節(jié)點(diǎn))的元素小于low的數(shù)值,那么應(yīng)該遞歸右子樹,并返回右子樹符合條件的頭結(jié)點(diǎn)。

代碼如下:

if(root->valright,low,high);//尋找符合區(qū)間[low,high]的節(jié)點(diǎn)
returnright;
}

如果root(當(dāng)前節(jié)點(diǎn))的元素大于high的,那么應(yīng)該遞歸左子樹,并返回左子樹符合條件的頭結(jié)點(diǎn)。

代碼如下:

if(root->val>high){
TreeNode*left=trimBST(root->left,low,high);//尋找符合區(qū)間[low,high]的節(jié)點(diǎn)
returnleft;
}

接下來要將下一層處理完左子樹的結(jié)果賦給root->left,處理完右子樹的結(jié)果賦給root->right。

最后返回root節(jié)點(diǎn),代碼如下:

root->left=trimBST(root->left,low,high);//root->left接入符合條件的左孩子
root->right=trimBST(root->right,low,high);//root->right接入符合條件的右孩子
returnroot;

此時(shí)大家是不是還沒發(fā)現(xiàn)這多余的節(jié)點(diǎn)究竟是如何從二叉樹中移除的呢?

在回顧一下上面的代碼,針對(duì)下圖中二叉樹的情況:

如下代碼相當(dāng)于把節(jié)點(diǎn)0的右孩子(節(jié)點(diǎn)2)返回給上一層,

if(root->valright,low,high);//尋找符合區(qū)間[low,high]的節(jié)點(diǎn)
returnright;
}

然后如下代碼相當(dāng)于用節(jié)點(diǎn)3的左孩子 把下一層返回的 節(jié)點(diǎn)0的右孩子(節(jié)點(diǎn)2) 接住。

root->left=trimBST(root->left,low,high);

此時(shí)節(jié)點(diǎn)3的右孩子就變成了節(jié)點(diǎn)2,將節(jié)點(diǎn)0從二叉樹中移除了。

最后整體代碼如下:

classSolution{
public:
TreeNode*trimBST(TreeNode*root,intlow,inthigh){
if(root==nullptr)returnnullptr;
if(root->valright,low,high);//尋找符合區(qū)間[low,high]的節(jié)點(diǎn)
returnright;
}
if(root->val>high){
TreeNode*left=trimBST(root->left,low,high);//尋找符合區(qū)間[low,high]的節(jié)點(diǎn)
returnleft;
}
root->left=trimBST(root->left,low,high);//root->left接入符合條件的左孩子
root->right=trimBST(root->right,low,high);//root->right接入符合條件的右孩子
returnroot;
}
};

精簡(jiǎn)之后代碼如下:

classSolution{
public:
TreeNode*trimBST(TreeNode*root,intlow,inthigh){
if(root==nullptr)returnnullptr;
if(root->valreturntrimBST(root->right,low,high);
if(root->val>high)returntrimBST(root->left,low,high);
root->left=trimBST(root->left,low,high);
root->right=trimBST(root->right,low,high);
returnroot;
}
};

只看代碼,其實(shí)不太好理解節(jié)點(diǎn)是符合移除的,這一塊大家可以自己在模擬模擬!

迭代法

因?yàn)槎嫠阉鳂涞挠行蛐裕恍枰褂脳DM遞歸的過程。

在剪枝的時(shí)候,可以分為三步:

  • 將root移動(dòng)到[L, R] 范圍內(nèi),注意是左閉右閉區(qū)間
  • 剪枝左子樹
  • 剪枝右子樹

代碼如下:

classSolution{
public:
TreeNode*trimBST(TreeNode*root,intL,intR){
if(!root)returnnullptr;

//處理頭結(jié)點(diǎn),讓root移動(dòng)到[L,R]范圍內(nèi),注意是左閉右閉
while(root!=nullptr&&(root->valval>R)){
if(root->valright;//小于L往右走
elseroot=root->left;//大于R往左走
}
TreeNode*cur=root;
//此時(shí)root已經(jīng)在[L,R]范圍內(nèi),處理左孩子元素小于L的情況
while(cur!=nullptr){
while(cur->left&&cur->left->valleft=cur->left->right;
}
cur=cur->left;
}
cur=root;

//此時(shí)root已經(jīng)在[L,R]范圍內(nèi),處理右孩子大于R的情況
while(cur!=nullptr){
while(cur->right&&cur->right->val>R){
cur->right=cur->right->left;
}
cur=cur->right;
}
returnroot;
}
};

總結(jié)

修剪二叉搜索樹其實(shí)并不難,但在遞歸法中大家可看出我費(fèi)了很大的功夫來講解如何刪除節(jié)點(diǎn)的,這個(gè)思路其實(shí)是比較繞的。

最終的代碼倒是很簡(jiǎn)潔。

如果不對(duì)遞歸有深刻的理解,這道題目還是有難度的!

本題我依然給出遞歸法和迭代法,初學(xué)者掌握遞歸就可以了,如果想進(jìn)一步學(xué)習(xí),就把迭代法也寫一寫。

其他語(yǔ)言版本

Java

classSolution{
publicTreeNodetrimBST(TreeNoderoot,intlow,inthigh){
if(root==null){
returnnull;
}
if(root.valreturntrimBST(root.right,low,high);
}
if(root.val>high){
returntrimBST(root.left,low,high);
}
//root在[low,high]范圍內(nèi)
root.left=trimBST(root.left,low,high);
root.right=trimBST(root.right,low,high);
returnroot;
}
}

Python

classSolution:
deftrimBST(self,root:TreeNode,low:int,high:int)->TreeNode:
ifnotroot:returnroot
ifroot.valreturnself.trimBST(root.right,low,high)//尋找符合區(qū)間[low,high]的節(jié)點(diǎn)
ifroot.val>high:
returnself.trimBST(root.left,low,high)//尋找符合區(qū)間[low,high]的節(jié)點(diǎn)
root.left=self.trimBST(root.left,low,high)//root->left接入符合條件的左孩子
root.right=self.trimBST(root.right,low,high)//root->right接入符合條件的右孩子
returnroot
責(zé)任編輯:haq

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

    關(guān)注

    96

    文章

    2946

    瀏覽量

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

    關(guān)注

    0

    文章

    74

    瀏覽量

    12375

原文標(biāo)題:修剪一棵二叉搜索樹

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

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    嵌入式學(xué)習(xí)-飛凌嵌入式ElfBoard ELF 1板卡-初識(shí)設(shè)備之設(shè)備組成和結(jié)構(gòu)

    的name和value。在設(shè)備中,可描述的信息包括:一、CPU的數(shù)量和類別;、內(nèi)存基地址和大小;三、總線和橋;四、外設(shè)連接;五、中斷控制器和中斷使用情況;六、GPIO控制器和GPIO使用情況;七
    發(fā)表于 01-08 08:32

    飛凌嵌入式ElfBoard ELF 1板卡-初識(shí)設(shè)備之設(shè)備組成和結(jié)構(gòu)

    的name和value。在設(shè)備中,可描述的信息包括:一、CPU的數(shù)量和類別;、內(nèi)存基地址和大小;三、總線和橋;四、外設(shè)連接;五、中斷控制器和中斷使用情況;六、GPIO控制器和GPIO使用情況;七
    發(fā)表于 01-07 09:16

    OpenAI推出ChatGPT搜索功能

    近日,OpenAI再次邁出了重要的一步,為其廣受好評(píng)的ChatGPT平臺(tái)添加了一項(xiàng)全新的搜索功能。 據(jù)悉,這項(xiàng)被命名為“ChatGPT搜索”的新功能,將為用戶帶來前所未有的搜索體驗(yàn)。以往,當(dāng)用戶需要
    的頭像 發(fā)表于 11-04 10:34 ?406次閱讀

    OpenAI在ChatGPT增添搜索功能

    近日,OpenAI宣布為其旗艦產(chǎn)品ChatGPT增添全新的搜索功能,此舉標(biāo)志著該公司對(duì)Alphabet旗下谷歌的直接挑戰(zhàn)進(jìn)一步升級(jí)。OpenAI周四正式揭曉了這一名為“ChatGPT搜索”的新功能
    的頭像 發(fā)表于 11-01 17:01 ?432次閱讀

    谷歌取消“站點(diǎn)鏈接搜索框”,適應(yīng)新搜索需求

    近日,谷歌發(fā)布了一則通知,決定取消搜索結(jié)果中的“站點(diǎn)鏈接搜索框”。這一功能已經(jīng)陪伴了用戶十多年,它允許用戶在特定網(wǎng)站上進(jìn)行更深入的搜索,為許多網(wǎng)民提供了便利。然而,隨著時(shí)代的變遷和技術(shù)的進(jìn)步,這一
    的頭像 發(fā)表于 10-23 11:20 ?387次閱讀

    什么是默克爾(Merkle Tree)?如何計(jì)算默克爾根?

    01 默克爾的概念 默克爾(Merkle Tree)是一種特殊的二叉樹,它的每個(gè)節(jié)點(diǎn)都存儲(chǔ)了一個(gè)數(shù)據(jù)塊的哈希值。哈希值是一種可以將任意長(zhǎng)度的數(shù)據(jù)轉(zhuǎn)換為固定長(zhǎng)度的字符串的算法,它具有唯一性和不可
    的頭像 發(fā)表于 09-30 18:22 ?1094次閱讀
    什么是默克爾<b class='flag-5'>樹</b>(Merkle Tree)?如何計(jì)算默克爾根?

    月訪問量超2億,增速113%!360AI搜索成為全球增速最快的AI搜索引擎

    和系統(tǒng)自動(dòng)匹配最佳模型,這使得360AI搜索獲得了獨(dú)一無的技術(shù)優(yōu)勢(shì)。除了通用大模型,360AI搜索還配備了眾多搜索場(chǎng)景專用模型,精準(zhǔn)提升特定場(chǎng)景下的
    的頭像 發(fā)表于 09-09 13:44 ?568次閱讀
    月訪問量超2億,增速113%!360AI<b class='flag-5'>搜索</b>成為全球增速最快的AI<b class='flag-5'>搜索</b>引擎

    AI搜索新貴彎道超車難

    新玩家高調(diào)入場(chǎng),老玩家默默升級(jí),搜索市場(chǎng)進(jìn)入新一輪洗牌階段。最近一段時(shí)間,老舊的搜索行業(yè)開出了新花。從2009年開始,谷歌、百度成了搜索領(lǐng)域繞不開的存在,它們占據(jù)了全球搜索引擎市場(chǎng)絕大
    的頭像 發(fā)表于 07-09 08:05 ?231次閱讀
    AI<b class='flag-5'>搜索</b>新貴彎道超車難

    指電極上覆蓋敏感材料的阻值計(jì)算

    覆蓋的敏感材料厚度超出指厚度時(shí)計(jì)算電阻,是否可以視作指電極指間電阻多個(gè)周期串聯(lián)后與超出指厚度部分敏感材料電阻并聯(lián)
    發(fā)表于 07-05 14:48

    指MOSFET器件靜電防護(hù)魯棒性提升技巧

    柵極接地NMOS是一種廣泛應(yīng)用的片上ESD器件結(jié)構(gòu),為達(dá)到特定ESD防護(hù)等級(jí),一般會(huì)采用多指版圖形式來減小器件占用的芯片面積。但是,多指柵極接地NMOS在ESD應(yīng)力作用下,各個(gè)指難于做到均勻
    的頭像 發(fā)表于 06-22 00:50 ?590次閱讀
    多<b class='flag-5'>叉</b>指MOSFET器件靜電防護(hù)魯棒性提升技巧

    AI商業(yè)化的考卷,360選了搜索來答

    廣告之外的第條路。隨著AI技術(shù)的發(fā)展,搜索引擎領(lǐng)域正經(jīng)歷巨大變革。截至今年4月,美國(guó)人工智能搜索公司PerplexityAI上線僅15個(gè)月,訪問量已突破10億次,迅速成為谷歌的重要競(jìng)爭(zhēng)對(duì)手。國(guó)內(nèi)
    的頭像 發(fā)表于 06-16 08:04 ?166次閱讀
    AI商業(yè)化的考卷,360選了<b class='flag-5'>搜索</b>來答

    原理圖設(shè)計(jì)里兩顆重要的(國(guó)產(chǎn)EDA)

    原理圖里面兩顆重要的,那就是元件和網(wǎng)絡(luò),作為EDA工具中的重要視圖和概念,雖然看似枯燥,但它們扮演著非常重要的角色,它們?yōu)殡娐穲D的層次化結(jié)構(gòu)提供了有力支撐。想象一個(gè)大型的電路設(shè)計(jì)項(xiàng)目,就像一個(gè)
    的頭像 發(fā)表于 05-29 17:47 ?828次閱讀
    原理圖設(shè)計(jì)里兩顆重要的<b class='flag-5'>樹</b>(國(guó)產(chǎn)EDA)

    圣誕燈電路圖分享

    圣誕裝飾的電路分為兩個(gè)主要部分,即燈光和聲音部分。照明部分由五組 LED 組成,它們以進(jìn)制順序運(yùn)行,每隔幾分鐘就會(huì)重復(fù)一次。在這里,根據(jù)我們的興趣,LED 可以是任何顏色。這件裝飾品可以裝飾您的圣誕以及您的家。
    的頭像 發(fā)表于 05-05 10:12 ?1252次閱讀
    圣誕<b class='flag-5'>樹</b>燈電路圖分享

    微軟推出Edge搜索欄,提升用戶搜索效率

    據(jù)4月19日消息,微軟近期推出Windows 11與Windows 10系統(tǒng)更新,新增Edge搜索欄桌面集成功能。官方表示,此舉旨在為用戶提供更便捷的搜索體驗(yàn),無需開啟瀏覽器即可獲得所需信息,從而提升工作效率。
    的頭像 發(fā)表于 04-19 14:44 ?735次閱讀

    Redis官方搜索引擎來了,性能炸裂!

    RediSearch 是一個(gè) Redis 模塊,為 Redis 提供查詢、級(jí)索引和全文搜索功能。
    的頭像 發(fā)表于 02-21 10:01 ?2538次閱讀
    Redis官方<b class='flag-5'>搜索</b>引擎來了,性能炸裂!
    博彩百家乐官网画谜网| 百家乐必赢| 一二博娱乐| 海威百家乐官网赌博机| 迪威百家乐赌场娱乐网规则| 民县| 百家乐官网具体怎么收费的| 百家乐五星宏辉怎么玩| 新营市| 网上百家乐骗人不| 澳门顶级赌场金沙| 百家乐官网娱乐礼金| 尊龙娱乐网| 在线百家乐娱乐| 大发888网址是多少| 百家乐官网博彩免费体验金3| 德州扑克高牌| 百家乐洗码| 龙博娱乐城| 百家乐庄闲的分布| 山东| 最好的百家乐好评平台都有哪些 | 新世纪娱乐城信誉怎么样| 百家乐官网庄牌| 足球开户| 百家乐电话投注怎么玩| 信博娱乐| 百家乐官网小音箱| 网络百家乐程序| 百家乐官网庄闲统计数| 六合彩历史开奖记录| ea百家乐打水| 蓝盾百家乐官网赌城| 环江| 威尼斯人娱乐网上百家乐| 百家乐官网游戏新| 衡水市| 百家乐网| 百家乐分路单析器| 澳门百家乐官网搏牌规则| 德州扑克怎么玩|