文章目录
- 1 题目
- 2 思路
- 3 ACM完整代码
- 参考
1 题目
给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵
平衡二叉搜索树
示例:
输入:nums = [-10,-3,0,5,9]
输出:[0,-3,9,-10,null,5]
解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案
2 思路
构造平衡二叉树?岂不是在不平衡的时候还需要左旋和右旋,这是对于一般的数组构建二叉平衡树来说的:就是当不满足任意一个左右子树高度之差的绝对值小于等于1的时候,需要进行旋转来保持二叉树的平衡。
但是这是一个排序好的数组,想一想,取中间的元素作为根元素,其余元素作为子树来构建二叉树,不是刚刚能达到平衡的条件吗?因为左右子树的个数都是一样的,如果还继续这样构造下去,一定能满足平衡的条件;想一想三个节点的情况,[1, 2, 3] 使用2作为根节点来构造
因此对于排序好的数组构建二叉平衡树,直接取中间元素作为根元素即可
注意:
对于奇数个元素还是偶数个元素取mid的问题,如果是奇数个,刚好能取到中间;如果是偶数个,则取中间两个的后一个;如果取前一个,都是正确的,所以才导致答案不唯一;
如何取mid?int mid = (left+right)/2;
还是int mid = left + (right - left)/2;
其实第一种有溢出的风险,如果left和right都是Integer.MAX_VALUE
就直接溢出了,计算结果错误,因此使用第二种更加合理
Code:
class Solution{
public TreeNode sortedArrayToBST(int[] nums) {
if (nums.length == 0) return null;
int left = 0, right = nums.length - 1;
TreeNode root = arrayToBST(nums, left, right);
return root;
}
private TreeNode arrayToBST(int[] nums, int left, int right) {
// 递归结束
if (left > right) {
return null;
}
int mid = left + ((right - left) / 2); // 寻找中点防溢出计算
TreeNode root = new TreeNode(nums[mid]);
root.left = arrayToBST(nums, left, mid - 1);
root.right = arrayToBST(nums, mid+1, right);
return root;
}
3 ACM完整代码
import java.util.*;
class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) {this.val = val; }
}
// Solution
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] nums = new int[n];
for (int i = 0; i < n; i++) {
nums[i] = in.nextInt();
}
Solution solution = new Solution();
TreeNode node = solution.sortedArrayToBST(nums);
preOrderTree(node);
}
static void preOrderTree(TreeNode root) {
if (root != null) {
System.out.print(root.val + " ");
preOrderTree(root.left);
preOrderTree(root.right);
}
}
}
/*
test case:
5
-10 -3 0 5 9
*/
参考
https://www.programmercarl.com/0108.将有序数组转换为二叉搜索树.html