日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

pta 是否完全二叉搜索树_二叉树:构造一棵搜索树

發(fā)布時(shí)間:2024/1/23 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 pta 是否完全二叉搜索树_二叉树:构造一棵搜索树 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
給「代碼隨想錄」一個(gè)星標(biāo)吧!?

構(gòu)造二叉搜索樹,一不小心就平衡了

?

108.將有序數(shù)組轉(zhuǎn)換為二叉搜索樹

將一個(gè)按照升序排列的有序數(shù)組,轉(zhuǎn)換為一棵高度平衡二叉搜索樹。

本題中,一個(gè)高度平衡二叉樹是指一個(gè)二叉樹每個(gè)節(jié)點(diǎn)?的左右兩個(gè)子樹的高度差的絕對(duì)值不超過 1。

示例:

108.將有序數(shù)組轉(zhuǎn)換為二叉搜索樹

思路

題目中說要轉(zhuǎn)換為一棵高度平衡二叉搜索樹。這和轉(zhuǎn)換為一棵普通二叉搜索樹有什么差別呢?

其實(shí)這里不用強(qiáng)調(diào)平衡二叉搜索樹,數(shù)組構(gòu)造二叉樹,構(gòu)成平衡樹是自然而然的事情,因?yàn)榇蠹夷J(rèn)都是從數(shù)組中間位置取值作為節(jié)點(diǎn)元素,一般不會(huì)隨機(jī)取,「所以想構(gòu)成不平衡的二叉樹是自找麻煩」

在二叉樹:構(gòu)造二叉樹登場(chǎng)!和二叉樹:構(gòu)造一棵最大的二叉樹中其實(shí)已經(jīng)講過了,如果根據(jù)數(shù)組構(gòu)造一顆二叉樹。

「本質(zhì)就是尋找分割點(diǎn),分割點(diǎn)作為當(dāng)前節(jié)點(diǎn),然后遞歸左區(qū)間和右區(qū)間」

本題其實(shí)要比二叉樹:構(gòu)造二叉樹登場(chǎng)! 和 二叉樹:構(gòu)造一棵最大的二叉樹簡(jiǎn)單一些,因?yàn)橛行驍?shù)組構(gòu)造二叉搜索樹,尋找分割點(diǎn)就比較容易了。

分割點(diǎn)就是數(shù)組中間位置的節(jié)點(diǎn)。

那么為問題來了,如果數(shù)組長(zhǎng)度為偶數(shù),中間節(jié)點(diǎn)有兩個(gè),取哪一個(gè)?

取哪一個(gè)都可以,只不過構(gòu)成了不同的平衡二叉搜索樹。

例如:輸入:[-10,-3,0,5,9]

如下兩棵樹,都是這個(gè)數(shù)組的平衡二叉搜索樹:

如果要分割的數(shù)組長(zhǎng)度為偶數(shù)的時(shí)候,中間元素為兩個(gè),是取左邊元素 ?就是樹1,取右邊元素就是樹2。

「這也是題目中強(qiáng)調(diào)答案不是唯一的原因。理解這一點(diǎn),這道題目算是理解到位了」

遞歸

遞歸三部曲:

  • 確定遞歸函數(shù)返回值及其參數(shù)

刪除二叉樹節(jié)點(diǎn),增加二叉樹節(jié)點(diǎn),都是用遞歸函數(shù)的返回值來完成,這樣是比較方便的。

相信大家如果仔細(xì)看了二叉樹:搜索樹中的插入操作和二叉樹:搜索樹中的刪除操作,一定會(huì)對(duì)遞歸函數(shù)返回值的作用深有感觸。

那么本題要構(gòu)造二叉樹,依然用遞歸函數(shù)的返回值來構(gòu)造中節(jié)點(diǎn)的左右孩子。

再來看參數(shù),首先是傳入數(shù)組,然后就是左下表left和右下表right,我們?cè)诙鏄?#xff1a;構(gòu)造二叉樹登場(chǎng)!中提過,在構(gòu)造二叉樹的時(shí)候盡量不要重新定義左右區(qū)間數(shù)組,而是用下表來操作原數(shù)組。

所以代碼如下:

//?左閉右閉區(qū)間[left,?right]
TreeNode*?traversal(vector&?nums,?int?left,?int?right)?

這里注意,「我這里定義的是左閉右閉區(qū)間,在不斷分割的過程中,也會(huì)堅(jiān)持左閉右閉的區(qū)間,這又涉及到我們講過的循環(huán)不變量」

在二叉樹:構(gòu)造二叉樹登場(chǎng)!,35.搜索插入位置 和59.螺旋矩陣II都詳細(xì)講過循環(huán)不變量。

  • 確定遞歸終止條件

這里定義的是左閉右閉的區(qū)間,所以當(dāng)區(qū)間 left > right的時(shí)候,就是空節(jié)點(diǎn)了。

代碼如下:

if?(left?>?right)?return?nullptr;
  • 確定單層遞歸的邏輯

首先取數(shù)組中間元素的位置,不難寫出int mid = (left + right) / 2;,「這么寫其實(shí)有一個(gè)問題,就是數(shù)值越界,例如left和right都是最大int,這么操作就越界了,在二分法中尤其需要注意!」

所以可以這么寫:int mid = left + ((right - left) / 2);

但本題leetcode的測(cè)試數(shù)據(jù)并不會(huì)越界,所以怎么寫都可以。但需要有這個(gè)意識(shí)!

取了中間位置,就開始以中間位置的元素構(gòu)造節(jié)點(diǎn),代碼:TreeNode* root = new TreeNode(nums[mid]);。

接著劃分區(qū)間,root的左孩子接住下一層左區(qū)間的構(gòu)造節(jié)點(diǎn),右孩子接住下一層右區(qū)間構(gòu)造的節(jié)點(diǎn)。

最后返回root節(jié)點(diǎn),單層遞歸整體代碼如下:

int?mid?=?left?+?((right?-?left)?/?2);?
TreeNode*?root?=?new?TreeNode(nums[mid]);
root->left?=?traversal(nums,?left,?mid?-?1);
root->right?=?traversal(nums,?mid?+?1,?right);
return?root;

這里int mid = left + ((right - left) / 2);的寫法相當(dāng)于是如果數(shù)組長(zhǎng)度為偶數(shù),中間位置有兩個(gè)元素,取靠左邊的。

  • 遞歸整體代碼如下:
class?Solution?{
private:
????TreeNode*?traversal(vector&?nums,?int?left,?int?right)?{if?(left?>?right)?return?nullptr;
????????int?mid?=?left?+?((right?-?left)?/?2);?
????????TreeNode*?root?=?new?TreeNode(nums[mid]);
????????root->left?=?traversal(nums,?left,?mid?-?1);
????????root->right?=?traversal(nums,?mid?+?1,?right);return?root;
????}
public:
????TreeNode*?sortedArrayToBST(vector&?nums)?{
????????TreeNode*?root?=?traversal(nums,?0,?nums.size()?-?1);return?root;
????}
};

「注意:在調(diào)用traversal的時(shí)候?yàn)槭裁磦魅氲膌eft和right為什么是0和nums.size() - 1,因?yàn)槎x的區(qū)間為左閉右閉」

迭代法

迭代法可以通過三個(gè)隊(duì)列來模擬,一個(gè)隊(duì)列放遍歷的節(jié)點(diǎn),一個(gè)隊(duì)列放左區(qū)間下表,一個(gè)隊(duì)列放右區(qū)間下表。

模擬的就是不斷分割的過程,C++代碼如下:(我已經(jīng)詳細(xì)注釋)

class?Solution?{
public:
????TreeNode*?sortedArrayToBST(vector&?nums)?{if?(nums.size()?==?0)?return?nullptr;
????????TreeNode*?root?=?new?TreeNode(0);???//?初始根節(jié)點(diǎn)
????????queue?nodeQue;???????????//?放遍歷的節(jié)點(diǎn)
????????queue?leftQue;?????????????????//?保存左區(qū)間下表
????????queue?rightQue;????????????????//?保存右區(qū)間下表
????????nodeQue.push(root);?????????????????//?根節(jié)點(diǎn)入隊(duì)列
????????leftQue.push(0);????????????????????//?0為左區(qū)間下表初始位置
????????rightQue.push(nums.size()?-?1);?????//?nums.size()?-?1為右區(qū)間下表初始位置while?(!nodeQue.empty())?{
????????????TreeNode*?curNode?=?nodeQue.front();
????????????nodeQue.pop();
????????????int?left?=?leftQue.front();?leftQue.pop();
????????????int?right?=?rightQue.front();?rightQue.pop();
????????????int?mid?=?left?+?((right?-?left)?/?2);
????????????curNode->val?=?nums[mid];???????//?將mid對(duì)應(yīng)的元素給中間節(jié)點(diǎn)if?(left?<=?mid?-?1)?{??????????//?處理左區(qū)間
????????????????curNode->left?=?new?TreeNode(0);
????????????????nodeQue.push(curNode->left);
????????????????leftQue.push(left);
????????????????rightQue.push(mid?-?1);
????????????}if?(right?>=?mid?+?1)?{?????????//?處理右區(qū)間
????????????????curNode->right?=?new?TreeNode(0);
????????????????nodeQue.push(curNode->right);
????????????????leftQue.push(mid?+?1);
????????????????rightQue.push(right);
????????????}
????????}return?root;
????}
};

總結(jié)

「在二叉樹:構(gòu)造二叉樹登場(chǎng)! 和 二叉樹:構(gòu)造一棵最大的二叉樹之后,我們順理成章的應(yīng)該構(gòu)造一下二叉搜索樹了,一不小心還是一棵平衡二叉搜索樹」

其實(shí)思路也是一樣的,不斷中間分割,然后遞歸處理左區(qū)間,右區(qū)間,也可以說是分治。

此時(shí)相信大家應(yīng)該對(duì)通過遞歸函數(shù)的返回值來增刪二叉樹很熟悉了,這也是常規(guī)操作。

在定義區(qū)間的過程中我們又一次強(qiáng)調(diào)了循環(huán)不變量的重要性。

最后依然給出迭代的方法,其實(shí)就是模擬取中間元素,然后不斷分割去構(gòu)造二叉樹的過程。

「就醬,如果對(duì)你有幫助的話,也轉(zhuǎn)發(fā)給身邊需要的同學(xué)吧!」

在留言區(qū)留下你的思路吧!

-------end-------

我將算法學(xué)習(xí)相關(guān)的資料已經(jīng)整理到了Github :https://github.com/youngyangyang04/leetcode-master,里面還有l(wèi)eetcode刷題攻略、各個(gè)類型經(jīng)典題目刷題順序、思維導(dǎo)圖看一看一定會(huì)有所收獲,如果給你有幫助給一個(gè)star支持一下吧!

另外因?yàn)楣娞?hào)改版,時(shí)間線被打亂,一些精彩文章大家可能錯(cuò)過了。如果感覺這里的文章對(duì)你有幫助,趕緊給「代碼隨想錄」加一個(gè)星標(biāo)吧,方便第一時(shí)間閱讀文章往期精彩回顧二叉樹:修剪一棵搜索樹二叉樹:搜索樹中的刪除操作二叉樹:搜索樹中的插入操作二叉樹:搜索樹的公共祖先問題本周小結(jié)!(二叉樹系列四)二叉樹:公共祖先問題二叉樹:我的眾數(shù)是多少?二叉樹:搜索樹的最小絕對(duì)差二叉樹:我是不是一棵二叉搜索樹二叉樹:二叉搜索樹登場(chǎng)!二叉樹:合并兩個(gè)二叉樹本周小結(jié)!(二叉樹系列三)二叉樹:構(gòu)造一棵最大的二叉樹二叉樹:構(gòu)造二叉樹登場(chǎng)!「代碼隨想錄」期待你的關(guān)注!

每天8:35準(zhǔn)時(shí)推送一道經(jīng)典算法題目,推送的每道題目都不是孤立的,而是由淺入深,環(huán)環(huán)相扣,幫你梳理算法知識(shí)脈絡(luò),輕松學(xué)算法!

刷題可以加我微信!右邊為個(gè)人微信,添加時(shí)備注:「簡(jiǎn)單自我介紹」+「組隊(duì)刷題」我就知道你[在看]

總結(jié)

以上是生活随笔為你收集整理的pta 是否完全二叉搜索树_二叉树:构造一棵搜索树的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。