<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          每日一道 LeetCode (24):將有序數(shù)組轉(zhuǎn)換為二叉搜索樹(shù)

          共 2861字,需瀏覽 6分鐘

           ·

          2020-08-20 11:14

          ?

          每天 3 分鐘,走上算法的逆襲之路。

          ?

          前文合集

          每日一道 LeetCode 前文合集

          代碼倉(cāng)庫(kù)

          GitHub:https://github.com/meteor1993/LeetCode

          Gitee:https://gitee.com/inwsy/LeetCode

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

          題目來(lái)源:https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/

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

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

          示例:

          給定有序數(shù)組: [-10,-3,0,5,9],

          一個(gè)可能的答案是:[0,-3,9,-10,null,5],它可以表示下面這個(gè)高度平衡二叉搜索樹(shù):

          ??????0
          ?????/?\
          ???-3???9
          ???/???/
          ?-10??5

          解題思路

          啥子玩意?還能通過(guò)一個(gè)數(shù)組逆推一個(gè)二叉樹(shù)出來(lái)?這題出的還敢再 BT 點(diǎn)不。

          絕對(duì)是神仙思路,玩不轉(zhuǎn)玩不轉(zhuǎn),直接投降翻答案。

          最開(kāi)始,需要明確一件事兒,啥是二叉搜索樹(shù)?

          二叉搜索的顯著特點(diǎn):

          • 對(duì)于樹(shù)中的每個(gè)節(jié)點(diǎn) X ,它的左子樹(shù)中所有關(guān)鍵字值小于 X 的關(guān)鍵字值,而它的右子樹(shù)中所有關(guān)鍵字值大于 X 的關(guān)鍵字值。

          簡(jiǎn)單來(lái)講就是 左 < 根 < 右。

          根據(jù)這個(gè)特性就有了,如果一個(gè)二叉搜索樹(shù)做中序遍歷,那么會(huì)得到一個(gè)遞增的序列。

          放到這道題里,就很明確了,這道題給出的數(shù)組序列實(shí)際上是一個(gè)中序遍歷的二叉搜索樹(shù)。

          官方的題解中,有幾個(gè)問(wèn)題比較好,我摘錄過(guò)來(lái)(以下內(nèi)容來(lái)源官方題解)。

          給定二叉搜索樹(shù)的中序遍歷,是否可以唯一地確定二叉搜索樹(shù)?答案是否定的。如果沒(méi)有要求二叉搜索樹(shù)的高度平衡,則任何一個(gè)數(shù)字都可以作為二叉搜索樹(shù)的根節(jié)點(diǎn),因此可能的二叉搜索樹(shù)有多個(gè)。

          如果增加一個(gè)限制條件,即要求二叉搜索樹(shù)的高度平衡,是否可以唯一地確定二叉搜索樹(shù)?答案仍然是否定的。

          直觀地看,我們可以選擇中間數(shù)字作為二叉搜索樹(shù)的根節(jié)點(diǎn),這樣分給左右子樹(shù)的數(shù)字個(gè)數(shù)相同或只相差 11,可以使得樹(shù)保持平衡。如果數(shù)組長(zhǎng)度是奇數(shù),則根節(jié)點(diǎn)的選擇是唯一的,如果數(shù)組長(zhǎng)度是偶數(shù),則可以選擇中間位置左邊的數(shù)字作為根節(jié)點(diǎn)或者選擇中間位置右邊的數(shù)字作為根節(jié)點(diǎn),選擇不同的數(shù)字作為根節(jié)點(diǎn)則創(chuàng)建的平衡二叉搜索樹(shù)也是不同的。

          到這一步,官方的題解已經(jīng)把最艱難的部分解決了 「如何確定一個(gè)根節(jié)點(diǎn)」 。

          下一步需要做的是把其余的數(shù)字放在二叉樹(shù)的左右子樹(shù)里面。

          那么如何放呢?很簡(jiǎn)單,我們重復(fù)剛才的過(guò)程,比如左子樹(shù),先找到左子樹(shù)的根節(jié)點(diǎn)(中間的那個(gè)數(shù)),然后遞歸這個(gè)過(guò)程。

          我只畫(huà)了兩次迭代,完整的畫(huà)完這個(gè)圖太大了, PPT 畫(huà)不下。

          官方題解上給出來(lái)三種解法,一種是選擇中間位置左邊的數(shù)字作為根節(jié)點(diǎn),另一種是選擇中間位置右邊的數(shù)字作為根節(jié)點(diǎn),最后一種是把前兩種結(jié)合起來(lái)。

          解題方案一:中序遍歷,選擇中間位置左邊的數(shù)字作為根節(jié)點(diǎn)

          選擇中間位置左邊的數(shù)字作為根節(jié)點(diǎn),則根節(jié)點(diǎn)的下標(biāo)為 mid = (left + right) / 2,此處的除法為整數(shù)除法。

          public?TreeNode?sortedArrayToBST(int[]?nums)?{
          ????return?helper(nums,?0,?nums.length?-?1);
          }

          //?中序遍歷,選擇中間位置左邊的數(shù)字作為根節(jié)點(diǎn)
          public?TreeNode?helper(int[]?nums,?int?left,?int?right)?{
          ????if?(left?>?right)?return?null;

          ????int?mid?=?(left?+?right)?/?2;

          ????TreeNode?node?=?new?TreeNode(nums[mid]);
          ????node.left?=?helper(nums,?left,?mid?-?1);
          ????node.right?=?helper(nums,?mid?+?1,?right);
          ????return?node;
          }

          解題方案二:中序遍歷,選擇中間位置右邊的數(shù)字作為根節(jié)點(diǎn)

          有了上面這個(gè)方案一,再寫(xiě)這個(gè)就已經(jīng)很簡(jiǎn)單了,在這個(gè)方案中,根節(jié)點(diǎn)的計(jì)算公式為 mid = (left + right + 1) / 2 。

          //?中序遍歷,選擇中間位置右邊的數(shù)字作為根節(jié)點(diǎn)
          public?TreeNode?helper_1(int[]?nums,?int?left,?int?right)?{
          ????if?(left?>?right)?return?null;

          ????int?mid?=?(left?+?right?+?1)?/?2;

          ????TreeNode?node?=?new?TreeNode(nums[mid]);
          ????node.left?=?helper(nums,?left,?mid?-?1);
          ????node.right?=?helper(nums,?mid?+?1,?right);
          ????return?node;
          }

          實(shí)際上有變化就只有 mid 的取值,剩下啥都沒(méi)變。

          解題方案三:中序遍歷,選擇任意一個(gè)中間位置數(shù)字作為根節(jié)點(diǎn)

          這個(gè)方案的 mid 取值就很有意思了,先不看后面,各位可以先思考下如何任意的取一個(gè)中間位置。

          也就是在 mid = (left + right) / 2mid = (left + right + 1) / 2 之間取一個(gè)值。

          官方的示例圖我先放出來(lái),別急著往下翻:

          結(jié)果是可以取一個(gè)隨機(jī)數(shù):mid = (left + right + new Random().nextInt(2)) / 2 。

          //?中序遍歷,選擇任意一個(gè)中間位置數(shù)字作為根節(jié)點(diǎn)
          public?TreeNode?helper_2(int[]?nums,?int?left,?int?right)?{
          ????if?(left?>?right)?return?null;

          ????int?mid?=?(left?+?right?+?new?Random().nextInt(2))?/?2;

          ????TreeNode?node?=?new?TreeNode(nums[mid]);
          ????node.left?=?helper(nums,?left,?mid?-?1);
          ????node.right?=?helper(nums,?mid?+?1,?right);
          ????return?node;
          }

          這個(gè)方案三的思路確實(shí)很清奇,有點(diǎn)意思。

          今天這道題需要通過(guò)一個(gè)數(shù)組逆推出來(lái)一個(gè)二叉搜索樹(shù),咳咳,第一次見(jiàn)確實(shí)不會(huì)做,就當(dāng)背答案了。

          感謝閱讀



          瀏覽 44
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  最新流出毛片视频 | 学生妹久久一次 | 人妻无码中文专区久久5566 | 久草综合在线视频 | 成人在线综合豆花 |