LeetCode 將一個按照升序排列的有序陣列,轉換為一棵高度平衡二叉搜尋樹
阿新 • • 發佈:2019-12-31
第108題
將一個按照升序排列的有序陣列,轉換為一棵高度平衡二叉搜尋樹。
本題中,一個高度平衡二叉樹是指一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過 1。
示例:
給定有序陣列: [-10,-3,0,5,9],一個可能的答案是:[0,9,-10,null,5],它可以表示下面這個高度平衡二叉搜尋樹:
0
/ \
-3 9
/ /
-10 5
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree
複製程式碼
解題思路
- 從定義我們知道,BST的中序遍歷為一個遞增序列,給定的陣列其實就是中序遍歷結果
- 取有序陣列的中間值做根,左邊部分做左樹,右邊部分做右樹如此迴圈迭代去二分就可還原這棵BST樹
程式碼實現
1.二分+遞迴實現
每次取陣列的中間值,作為二分搜尋樹的中間節點,依次遞迴下去即可
//二分+遞迴實現
class Solution108_1 {
public TreeNode sortedArrayToBST(int[] nums) {
return convertToBST(nums,nums.length - 1);
}
TreeNode convertToBST(int[] nums,int begin,int end) {
if (begin > end) return null;
//取中值
int mid = begin + (end - begin) / 2;
TreeNode root = new TreeNode(nums[mid]);
//左葉子樹
root.left = convertToBST(nums,begin,mid - 1);
//右葉子樹
root.right = convertToBST(nums,mid + 1,end);
return root;
}
}
複製程式碼
2.利用堆疊,去遞迴化實現
- 定義一個棧,用來存將要處理陣列的左索引和右索引值
- 定義另一個棧,用來存樹的節點,因為節點是先初始化,後更新節點值的迭代過程。所以需要借用堆疊先建好節點,建立好關係。
//非遞迴實現
class Solution108_2 {
public TreeNode sortedArrayToBST(int[] nums) {
if (nums == null || nums.length == 0) return null;
Stack<Integer> stack = new Stack<Integer>();
//陣列最大索引值入棧
stack.add(nums.length - 1);
//陣列最小索引值入棧
stack.add(0);
Stack<TreeNode> tree = new Stack<TreeNode>();
TreeNode root = new TreeNode(0);
//隨便new樹節點入棧
tree.add(root);
while (!stack.isEmpty()) {
int left = stack.pop();
int right = stack.pop();
//求出中間節點索引值
int mid = left + (right - left) / 2;
TreeNode node = tree.pop();
//更新根節點值
node.val = nums[mid];
//計算左葉子節點最大最小索引值
int r = mid - 1,l = left;
//如果存在左葉子節點
if (l <= r) {
node.left = new TreeNode(0);
//隨便new個樹節點入棧
tree.add(node.left);
//對應右索引值入棧
stack.push(r);
//對應左索引值入棧
stack.push(l);
}
//計算右節點最大最小索引值
l = mid + 1;
r = right;
if (l <= r) {
node.right = new TreeNode(0);
//隨便new個樹節點入棧
tree.add(node.right);
//對應右索引值入棧
stack.push(r);
//對應左索引值入棧
stack.add(l);
}
}
return root;
}
}
複製程式碼
總結
不出所料,通過提交程式碼發現堆疊實現會比遞迴執行效率慢很多,這是因為:
- 堆疊實現需要頻繁的push(入棧)、pop(出棧)操作導致效能下降