這道題是LeetCode裏的第108道題。
題目描述:
將一個按照升序排列的有序數組,轉換爲一棵高度平衡二叉搜索樹。
本題中,一個高度平衡二叉樹是指一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過 1。
示例:
給定有序數組: [-10,-3,0,5,9], 一個可能的答案是:[0,-3,9,-10,null,5],它可以表示下面這個高度平衡二叉搜索樹: 0 / \ -3 9 / / -10 5
二分法,分治法。我們可以考慮把一個大的問題分解成爲幾個小的問題。
首先二分法肯定是確認的,因爲要保證樹結構是有序的,這個我親自驗證過了。
另外還需注意求中值 m 的時候,最好不要 (l + r) / 2 這樣計算,可能會加法溢出,最安全的方法是 m = l + (r - l) / 2,就如同計算:x * x > y 不如 x > y / x 好。這些細節都有可能是面試的加分項,更厲害點可以把 m = l + (r - l) / 2 改成 m = l + ((r - l) >> 1)。
解題代碼:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return nums == null ? null : buildTree(nums, 0, nums.length - 1);
}
private TreeNode buildTree(int[] nums, int l, int r) {
if (l > r) {
return null;
}
// int m = l + ((r - l) >> 1);
int m = l + (r - l) / 2;
TreeNode root = new TreeNode(nums[m]);
root.left = buildTree(nums, l, m - 1);
root.right = buildTree(nums, m + 1, r);
return root;
}
}
提交結果:
個人總結:
這道題我不想使用遞歸做,使用迭代卻因爲無法處理進出棧的順序而無法完成任務。
堆棧迭代做法:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
private class Node{
int low, up;
TreeNode t;
Node(int l, int p, TreeNode node){
low = l;
up = p;
t = node;
}
}
public TreeNode sortedArrayToBST(int[] nums) {
if(nums == null || nums.length == 0)return null;
// initialize
Stack<Node> stack = new Stack<Node>();
TreeNode root = new TreeNode(nums[(nums.length - 1)/2]);
Node rootNode = new Node(0, nums.length - 1, root);
stack.push(rootNode);
// iteration
while(!stack.isEmpty()) {
Node node = stack.pop();
int middle = (node.low + node.up) / 2;// cut half for [low, up]
// [low, middle - 1]
if(middle - 1 >= node.low) {
TreeNode leftnode = new TreeNode(nums[(middle-1+node.low)/2]);
node.t.left = leftnode;
Node left = new Node(node.low, middle - 1, leftnode);
stack.push(left);
}
// [middle + 1, up]
if(middle + 1 <= node.up) {
TreeNode rightnode = new TreeNode(nums[(middle+1+node.up)/2]);
node.t.right = rightnode;
Node right = new Node(middle+1, node.up, rightnode);
stack.push(right);
}
}
return root;
}
}
太強了!