第108題
將一個按照升序排列的有序數組,轉換為一棵高度平衡二叉搜索樹。
本題中,一個高度平衡二叉樹是指一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過 1。
示例:
給定有序數組: [-10,-3,0,5,9],
一個可能的答案是:[0,-3,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, 0, 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(出棧)操作導致性能下降