国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

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

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

[[422335]]

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

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

力扣題目鏈接:https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree

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

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

示例:

思路

做這道題目之前大家可以了解一下這幾道:

  • 從中序與后序遍歷序列構(gòu)造二叉樹
  • 最大二叉樹
  • 二叉搜索樹中的插入操作
  • 刪除二叉搜索樹中的節(jié)點(diǎn)

進(jì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ù)組轉(zhuǎn)換為二叉搜索樹

如果要分割的數(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è)诙鏄洌簶?gòu)造二叉樹登場(chǎng)!中提過,在構(gòu)造二叉樹的時(shí)候盡量不要重新定義左右區(qū)間數(shù)組,而是用下表來操作原數(shù)組。

所以代碼如下:

  1. // 左閉右閉區(qū)間[leftright
  2. TreeNode* traversal(vector<int>& nums, int leftint right

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

數(shù)組:每次遇到二分法,都是一看就會(huì),一寫就廢;nj 在二叉樹:構(gòu)造二叉樹登場(chǎng)!,704. 二分查找 和59.螺旋矩陣II都詳細(xì)講過循環(huán)不變量。

  • 確定遞歸終止條件

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

代碼如下:

  1. if (left > rightreturn 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),單層遞歸整體代碼如下:

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

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

  • 遞歸整體代碼如下:
  1. class Solution { 
  2. private: 
  3.     TreeNode* traversal(vector<int>& nums, int leftint right) { 
  4.         if (left > rightreturn nullptr; 
  5.         int mid = left + ((right - left) / 2); 
  6.         TreeNode* root = new TreeNode(nums[mid]); 
  7.         root->left = traversal(nums, left, mid - 1); 
  8.         root->right = traversal(nums, mid + 1, right); 
  9.         return root; 
  10.     } 
  11. public
  12.     TreeNode* sortedArrayToBST(vector<int>& nums) { 
  13.         TreeNode* root = traversal(nums, 0, nums.size() - 1); 
  14.         return root; 
  15.     } 
  16. }; 

注意:在調(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ì)注釋)

  1. class Solution { 
  2. public
  3.     TreeNode* sortedArrayToBST(vector<int>& nums) { 
  4.         if (nums.size() == 0) return nullptr; 
  5.  
  6.         TreeNode* root = new TreeNode(0);   // 初始根節(jié)點(diǎn) 
  7.         queue<TreeNode*> nodeQue;           // 放遍歷的節(jié)點(diǎn) 
  8.         queue<int> leftQue;                 // 保存左區(qū)間下表 
  9.         queue<int> rightQue;                // 保存右區(qū)間下表 
  10.         nodeQue.push(root);                 // 根節(jié)點(diǎn)入隊(duì)列 
  11.         leftQue.push(0);                    // 0為左區(qū)間下表初始位置 
  12.         rightQue.push(nums.size() - 1);     // nums.size() - 1為右區(qū)間下表初始位置 
  13.  
  14.         while (!nodeQue.empty()) { 
  15.             TreeNode* curNode = nodeQue.front(); 
  16.             nodeQue.pop(); 
  17.             int left = leftQue.front(); leftQue.pop(); 
  18.             int right = rightQue.front(); rightQue.pop(); 
  19.             int mid = left + ((right - left) / 2); 
  20.  
  21.             curNode->val = nums[mid];       // 將mid對(duì)應(yīng)的元素給中間節(jié)點(diǎn) 
  22.  
  23.             if (left <= mid - 1) {          // 處理左區(qū)間 
  24.                 curNode->left = new TreeNode(0); 
  25.                 nodeQue.push(curNode->left); 
  26.                 leftQue.push(left); 
  27.                 rightQue.push(mid - 1); 
  28.             } 
  29.  
  30.             if (right >= mid + 1) {         // 處理右區(qū)間 
  31.                 curNode->right = new TreeNode(0); 
  32.                 nodeQue.push(curNode->right); 
  33.                 leftQue.push(mid + 1); 
  34.                 rightQue.push(right); 
  35.             } 
  36.         } 
  37.         return root; 
  38.     } 
  39. }; 

總結(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)造二叉樹的過程。

其他語言版本

Java

遞歸: 左閉右閉 [left,right]

  1. class Solution { 
  2.  public TreeNode sortedArrayToBST(int[] nums) { 
  3.   TreeNode root = traversal(nums, 0, nums.length - 1); 
  4.   return root; 
  5.  } 
  6.  
  7.  // 左閉右閉區(qū)間[leftright
  8.  private TreeNode traversal(int[] nums, int leftint right) { 
  9.   if (left > rightreturn null
  10.  
  11.   int mid = left + ((right - left) >> 1); 
  12.   TreeNode root = new TreeNode(nums[mid]); 
  13.   root.left = traversal(nums, left, mid - 1); 
  14.   root.right = traversal(nums, mid + 1, right); 
  15.   return root; 
  16.  } 

迭代: 左閉右閉 [left,right]

  1. class Solution { 
  2.  public TreeNode sortedArrayToBST(int[] nums) { 
  3.   if (nums.length == 0) return null
  4.  
  5.   //根節(jié)點(diǎn)初始化 
  6.   TreeNode root = new TreeNode(-1); 
  7.   Queue<TreeNode> nodeQueue = new LinkedList<>(); 
  8.   Queue<Integer> leftQueue = new LinkedList<>(); 
  9.   Queue<Integer> rightQueue = new LinkedList<>(); 
  10.  
  11.   // 根節(jié)點(diǎn)入隊(duì)列 
  12.   nodeQueue.offer(root); 
  13.   // 0為左區(qū)間下表初始位置 
  14.   leftQueue.offer(0); 
  15.   // nums.size() - 1為右區(qū)間下表初始位置 
  16.   rightQueue.offer(nums.length - 1); 
  17.  
  18.   while (!nodeQueue.isEmpty()) { 
  19.    TreeNode currNode = nodeQueue.poll(); 
  20.    int left = leftQueue.poll(); 
  21.    int right = rightQueue.poll(); 
  22.    int mid = left + ((right - left) >> 1); 
  23.  
  24.    // 將mid對(duì)應(yīng)的元素給中間節(jié)點(diǎn) 
  25.    currNode.val = nums[mid]; 
  26.  
  27.    // 處理左區(qū)間 
  28.    if (left <= mid - 1) { 
  29.     currNode.left = new TreeNode(-1); 
  30.     nodeQueue.offer(currNode.left); 
  31.     leftQueue.offer(left); 
  32.     rightQueue.offer(mid - 1); 
  33.    } 
  34.  
  35.    // 處理右區(qū)間 
  36.    if (right >= mid + 1) { 
  37.     currNode.right = new TreeNode(-1); 
  38.     nodeQueue.offer(currNode.right); 
  39.     leftQueue.offer(mid + 1); 
  40.     rightQueue.offer(right); 
  41.    } 
  42.   } 
  43.   return root; 
  44.  } 

Python

遞歸法:

  1. class Solution: 
  2.     def sortedArrayToBST(self, nums: List[int]) -> TreeNode: 
  3.         def buildaTree(left,right): 
  4.             if left > rightreturn None  #左閉右閉的區(qū)間,當(dāng)區(qū)間 left > right的時(shí)候,就是空節(jié)點(diǎn),當(dāng)left = right的時(shí)候,不為空 
  5.             mid = left + (right - left) // 2 #保證數(shù)據(jù)不會(huì)越界 
  6.             val = nums[mid] 
  7.             root = TreeNode(val) 
  8.             root.left = buildaTree(left,mid - 1) 
  9.             root.right = buildaTree(mid + 1,right
  10.             return root 
  11.         root = buildaTree(0,len(nums) - 1)  #左閉右閉區(qū)間 
  12.         return root 

本文轉(zhuǎn)載自微信公眾號(hào)「代碼隨想錄」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系代碼隨想錄公眾號(hào)。

 

責(zé)任編輯:武曉燕 來源: 代碼隨想錄
相關(guān)推薦

2021-12-07 06:55:17

二叉搜索樹鏈表

2022-12-26 00:51:33

雙向鏈表二叉搜索樹

2021-08-31 11:35:24

二叉搜索樹迭代法公共祖先

2021-09-02 11:31:28

二叉搜索樹迭代法公共祖先

2022-01-11 10:01:25

二叉搜索樹數(shù)量

2023-07-31 08:01:13

二叉搜索測(cè)試

2021-09-03 08:58:00

二叉搜索樹節(jié)點(diǎn)

2020-04-27 07:05:58

二叉樹左子樹右子樹

2024-01-17 07:36:50

二叉搜索聯(lián)系簿

2021-08-26 11:31:11

二叉樹數(shù)據(jù)結(jié)構(gòu)算法

2023-02-13 08:02:08

哈希函數(shù)哈希表搜索樹

2022-09-21 07:57:33

二叉搜索樹排序二叉樹

2021-10-11 06:38:52

遞歸二叉搜索樹

2021-09-06 10:38:50

二叉搜索樹遞歸

2020-10-11 16:56:48

二叉搜索樹代碼開發(fā)

2019-11-04 10:06:19

MySQL索引

2021-04-06 08:20:24

二叉搜索樹數(shù)據(jù)結(jié)構(gòu)算法

2020-09-23 18:25:40

算法二叉樹多叉樹

2021-09-29 10:19:00

算法平衡二叉樹

2023-08-29 08:31:13

B+樹數(shù)據(jù)索引
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

97超级碰碰| 69久久夜色精品国产7777| av中文字幕av| av一区二区在线播放| 欧美精品日韩一区| 亚洲五月天综合| 丝袜a∨在线一区二区三区不卡| 欧美久久精品一级黑人c片| www.在线播放| 中文字幕成人在线观看| 国产精品人人爽人人做我的可爱 | www日韩av| **国产精品| 日韩成人激情视频| 免费成人av电影| 俺要去色综合狠狠| 亚洲视频在线免费看| 91吃瓜网在线观看| 一区二区三区91| www日韩在线观看| 国产91精品久久久久久久网曝门 | 久久嫩草精品久久久精品| 欧美极品日韩| 亚洲激情中文| 国产精品美乳一区二区免费| 欧美专区一区| 日韩中文字幕在线精品| 日本蜜桃在线观看视频| 欧美成人a在线| 污污影院在线观看| 欧美浪妇xxxx高跟鞋交| 大地资源中文在线观看免费版| 一区二区三区欧美亚洲| 中文字幕在线综合| 国产欧美日韩精品一区| 成人免费视频91| 国产**成人网毛片九色 | 国产一区二区三区日韩| 动漫一区二区在线| 成年在线观看免费人视频| 亚洲国产一区二区在线播放| 欧美色老女人| 亚洲男同性恋视频| 午夜视频免费在线观看| 亚洲深夜激情| 国产99视频精品免费视频36| 午夜日本精品| 国产精品区一区二区三在线播放 | 欧洲一区二区在线观看| 午夜亚洲视频| 欧洲一区二区在线观看| 日本亚洲最大的色成网站www| 水蜜桃一区二区三区| 麻豆精品在线视频| 男女激情免费视频| 国产亚洲成aⅴ人片在线观看| 成年网站在线播放| 亚洲综合偷拍欧美一区色| 亚洲福利二区| 欧美一级在线观看| 无遮挡爽大片在线观看视频| 久久精品国产欧美激情| 丝袜美腿综合| 精品国产一区二区三区免费| 久久97超碰色| 免费激情视频在线观看| 亚洲图片有声小说| 黄色小网站在线观看| 亚洲天堂av在线播放| 国产精品45p| 91九色单男在线观看| 国产欧美69| 日韩欧美视频免费在线观看| 欧美极品另类videosde| 欧美另类极限扩张| 亚洲第一中文字幕| 999久久久久久久久6666| 91免费看蜜桃| 成人激情视频网站| 成人两性免费视频| 一本久道综合久久精品| 久久久久久久久久伊人| 综合久久给合久久狠狠狠97色| 国产成年人在线观看| 99免费精品视频| 中文在线观看视频| 精品1区2区在线观看| 警花av一区二区三区| 亚洲mm色国产网站| 国产一区二区影院| 成视频年人免费看黄网站| 91精品国产欧美一区二区18| 国产一区二区三区黄网站| 99在线观看| 久久综合色综合88| 在线看免费av| 久久久久久久久久久免费 | 一区二区三区四区在线| av片哪里在线观看| 久久久久国色av免费观看性色| 51精产品一区一区三区| 欧美日韩视频免费在线观看| 亚洲午夜激情网站| 精品裸体bbb| 欧美精品在线观看播放| 四虎永久精品在线| 亚洲美女动态图120秒| 国产女人在线视频| 俺去啦;欧美日韩| 亚洲国产高清一区| 欧美精品性生活| 制服.丝袜.亚洲.中文.综合| 国产精品香蕉| 在线观看成人免费| 一本大道久久a久久精二百| 色狠狠一区二区三区| 欧洲亚洲一区| 色综合婷婷久久| 国内精品国产成人国产三级粉色| 亚洲欧美日韩国产yyy| 色综合久久久久综合99| 成人偷拍自拍| 99热这里只有精品7| 欧美日韩免费高清一区色橹橹 | 91久久精品一区二区三区| 黄色影院一级片| 久久99国产精品成人| 全部a∨一极品视觉盛宴| 中文字幕成人在线| 日韩一级视频免费观看在线| 福利电影一区| 手机福利在线视频| 日本韩国欧美三级| 亚洲人成精品久久久| 免费观看日韩毛片| 日韩精品中文字| 香蕉久久夜色精品| 天堂成人在线| 国产成人av在线播放| 国产亚洲精品免费| free欧美| 少妇高潮大叫好爽喷水| 91精品国产91久久综合桃花| 欧美一区免费| 色天堂在线视频| 国产精品嫩草视频| 一区在线观看视频| 加勒比色综合久久久久久久久| 免费在线a视频| 日韩在线免费高清视频| 国产精品1区2区3区| 国产盗摄——sm在线视频| 精品国产中文字幕| 欧美精品一卡二卡| 国产一区二区高清| 成年人视频在线免费观看| 亚洲一区国产精品| 色悠悠久久综合| 亚洲字幕久久| 日韩欧美在线一区二区| 欧美日韩中字一区| 一区二区自拍| 国产原创在线观看| 午夜欧美性电影| 亚洲人成电影在线| av爱爱亚洲一区| 91成人精品在线| www.4438全国最大| 国产精品中文字幕久久久| 日本国产一区二区| 亚洲欧美日韩国产综合精品二区| 成人影院在线播放| 在线成人性视频| 色妞在线综合亚洲欧美| 国产欧美日韩亚州综合| 成人在线电影在线观看视频| 三级视频在线| 在线视频观看一区| 99在线精品视频在线观看 | 亚洲国产精品精华液2区45| 久久久久毛片免费观看| 黄页免费观看| 国产激情一区二区三区在线观看| 日韩一区二区在线播放| 国产福利一区在线| 涩爱av色老久久精品偷偷鲁| 3344永久| 国产精品嫩草在线观看| 精品五月天久久| 国产日韩欧美电影| 精品国产一区二区三区四区 | 你懂的在线看| 六十路精品视频| 亚洲最新av网址| 中文字幕在线一区| 国产一区激情| 欧美一区久久久| 欧美vide| 国产资源第一页| 国产欧美一区二区|