描述
给出一个升序排序的数组,将其转化为平衡二叉搜索树(BST).
示例1
输入:
[-1,0,1,2]
复制返回值:
{1,0,2,-1}
先了解一下平衡二叉搜索树的特点。
二叉搜索树,它的中序遍历后的结果就是一个升序的序列;
平衡的,说明任何一个节点的左子树和右子树的高度相差不超过1。
题目中所给的是一个升序排序的数组,所以一个大体流程就是根据一个中序遍历的序列,还原出一个它对应的二叉树。因为是中序遍历的结果,所以元素的左边都是以该元素为根节点的左子树上的元素,元素的右边都是以该元素为根节点的右子树上的元素。
又因为是平衡的,所以先找出序列的中点,以中点的值生成根节点,他的左边右边相差不差过一个元素,即它的左子树和右子树的元素个数相差不超过一个,每次都安一样的策略来找根节点,即左右子树的高度相差不会超过1。
以中点的左边序列为一个新的序列,按照一样的方法生成一个平衡二叉树,该树是第一步找的根节点的左子树。
以中点的右边序列为一个新的序列,按照一样的方法生成一个平衡二叉树,该树是第一步找的根节点的右子树。
public class Solution {
/**
*
* @param num int整型一维数组
* @return TreeNode类
*/
public TreeNode sortedArrayToBST (int[] nums) {
// 判断特殊情况, 数组为空,或数组上没有元素,直接返回 null
if (nums == null || nums.length == 0) {
return null;
}
return process(nums, 0, nums.length - 1);
}
/**
*
* @param nums 整个的有序数组
* @param left 数组的左边界, 闭区间
* @param right 数组的右边界, 闭区间
* @return nums[left ... right] 这个范围的数组,转成 BST 后的根节点
*/
public TreeNode process(int[] nums, int left, int right) {
// 左边界 比 右边界 大, 说明数组上没有元素,直接返回 null
if (left > right) {
return null;
}
// 如果只有一个元素,就把它当成根节点直接返回
if (left == right) {
TreeNode root = new TreeNode(nums[left]);
return root;
}
// nums[left ... right] 这个数组的长度
int len = right - left + 1;
// nums[left ... right] 这个数组的中点下标,这个下标里的元素值就是 BST 的根节点的值
int mid = left + len / 2;
TreeNode root = new TreeNode(nums[mid]);
// 找出根节点的左子树: 继续递归用这个方法,找出左子树上这个局部范围的BST的根节点
root.left = process(nums, left, mid - 1);
// 找出根节点的右子树: 继续递归用这个方法,找出右子树上这个局部范围的BST的根节点
root.right = process(nums, mid + 1, right);
return root;
}
}
方法二,借助两个栈进行迭代
- 维护两个stack,一个保存结果,一个保存每次迭代的左右分界点
- 迭代每个数组每个元素,先获取当前区间,以及当前区间根节点在数组的位置
- 构造当前结点,接着根据左右区间,分别构建左右子节点
- 每次都要更新保存左右分界点的stack
import java.util.*;
public class Solution {
public TreeNode sortedArrayToBST (int[] num) {
if(num == null || num.length == 0) {
return null;
}
// 保存结果
Stack<TreeNode> res = new Stack<>();
// 保存左右分界点
Stack<Integer> stack = new Stack<>();
// 初始化根节点
TreeNode root = new TreeNode(0);
res.push(root);
stack.push(0);
stack.push(num.length - 1);
while(res.size() > 0) {
// 获取当前区间
int right = stack.pop();
int left = stack.pop();
// 当前区间根节点在数组的位置
int mid = left + ((right - left + 1) >> 1);
TreeNode node = res.pop();
// 当前区间的根节点赋值
node.val = num[mid];
// 左区间,构建左子节点
if(left <= mid - 1) {
node.left = new TreeNode(0);
// 初始化左子节点,为了下次构建二叉树
res.push(node.left);
stack.push(left);
// 缩小为左区间
stack.push(mid - 1);
}
// 右区间,构建右子节点
if(right >= mid + 1) {
node.right = new TreeNode(0);
res.push(node.right);
stack.push(mid + 1);
stack.push(right);
}
}
return root;
}
}