Featured image of post 從LeetCode學演算法 - 35 BST (3)

從LeetCode學演算法 - 35 BST (3)

0108. Convert Sorted Array to Binary Search Tree (Easy)

Question

Given an array where elements are sorted in ascending order, convert it to a height balanced BST.

For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differs by more than 1.

Example:

1
Given the sorted array: [-10,-3,0,5,9],
1
One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST:
1
2
3
4
5
      0
     / \
   -3   9
   /   /
 -10  5

分析/解題

給定一個陣列,其元素以升冪排序 (也就是後面的一定比前面大),
試將其轉成一個高度平衡的二元搜尋樹。

高度平衡的樹由於已在先前的題目中講過了(0110. Balanced Binary Tree),
這邊就不再贅述,簡言之就是對每個節點,
其兩邊的子樹深度相差均<=1就對了!

我們知道要達到這個條件,最基本的就是一個root的左右兩邊要公平,
所以最簡單的作法就是取中位數作為根,其左邊就是左子樹的所有節點,
右邊就是右子樹的所有節點;再分別讓各自的左右子樹再次拆分,直到分到沒有節點為止。

這樣作可以讓每一層都均分節點,從而讓每個分支的深度基本接近一致。
故整體流程如下:

  1. 檢查陣列是否是空的或者null,是的話直接回傳
  2. 呼叫一個用來遞迴建立BST的函式,這邊命名成getNode()
  3. getNode會輸入陣列以及當下的左右邊界(nums, l, r) 
    (一開始l = 0, r = N-1, N是nums的總數)
  4. 每次先檢查左右邊界是否黃金交叉(表示已經完成了,可以回傳null)
  5. 讓mid = l加r的一半,直接建立一個root節點
  6. root節點的左節點 就應該是呼叫getNode(nums, l, mid-1) 得到的結果
  7. root節點的右節點 則會是getNode(nums, mid+1, r) 得到的結果
  8. 回傳root

我們可以看到每次會抓中間值產生一個節點,再利用已排序的特性,
繼續進入遞迴往下將左邊和右邊的節點處理完畢。
思考它的執行流程,應該會發現總體而言我們會先一路來到最左邊的節點,
再回頭建立每個遞迴函式的右邊節點;
也就是說,程式執行的優先順序是先往深處的方向走 而非先將這一層的狀況處理完,這種模式我們稱之為深度優先搜尋(Depth-First Search, DFS)
如果換作是優先順序是先廣泛地處理完這一層,再往下一層走 ,這種模式就稱之為廣度優先搜尋(Breadth-First Search, BFS)

程式碼的部分,僅需留意Java因為想避免overflow的狀況,
計算的方式為 start + (end - start) / 2 ,而非(start + end) / 2。

Java

Python

面試實際可能會遇到的問題

「時間/空間複雜度?」
(O(N), O(N)
每個節點都會掃過一遍,且基本和其他節點沒有太多連帶關係。)

「那麼如果要將一個BST轉成排序陣列 呢?」
(原則上可用Inorder Traversal
但留意不加NIL的狀況其實中間樹的架構資訊可能會就此流失掉)

相似及延伸

  1. 0109. Convert Sorted List to Binary Search Tree (起始給的從陣列/串列改成排序好的LinkedList)

Special Thanks suggestions/corrections from viewers:
(歡迎提供意見協助更正歐~)

從LeetCode學演算法,我們下次見囉,掰~

共發表了 171 篇文章 ‧ 總計 311.6k
使用 Hugo 建立
主題 StackJimmy 設計