1. 题目描述
将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
2. 示例
3. 思路
- 第一反应就是,既然数组有序,那我从中间开始不就行了嘛,接着是思考了数组单数双数有无影响,发现无影响。接着两边插入就行
4. 遇上的问题
问题1:
- 在确定完树的起点(数组中值)之后,确定左右子树节点,发现,不能直接走相邻的点。 相邻点会导致左右子树高度相差超过1.
解决方法:
- 在继续现在中值的左右区间的中值让他作为子节点,左区间中值做左节点的值,右区间中值做右节点的值。
问题2:
- 在进行末端节点值赋值的时候,会发现当一层子节点都是空的时候,不能计入这一层的值(包括null对象),
解决方法2:
- 在进行末端节点赋值的时候先进行判断,跳过末端节点循环即可。
问题3:
- 在进行节点初始化的时候会自动生成一个子树让其值默认为0的情况,导致原本是null的地方变成了0。
解决方法3:
- 在初始化的时候让所有子树都为null,不让他有默认值的机会
5. 具体实现代码
自己写的代码
/**
* 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) {
//确定数组末端值
int last = nums.length-1;
//坑1,nums为null判断失效??
//通过末端值判断数组是否为空
if(last==-1) return null;
//获得前端值
int first =0;
//获得中值
int mid = first + (last-first)/2;
//创建根节点
TreeNode node = new TreeNode(nums[mid]);
//当中值-1小于起始值的时候,说明中值==起始值,中值左端已空,不用继续遍历左子树
if(first>mid-1) node.left = null;
else{
//否则生成左节点,并进入循环
node.left = new TreeNode();
//first,mid-1是需要插入树的区间范围
sortedArrayToBST1(nums,first,mid-1,node.left);
}
//当中值+1大于末端值的时候,说明中值==末端值,中值右端已空,不用继续遍历右子树
if(mid+1>last) node.right = null;
else{
//否则生成右节点,并进入循环
node.right = new TreeNode();
//mid+1,last是需要插入树的区间范围
sortedArrayToBST1(nums,mid+1,last,node.right);
}
return node;
}
public TreeNode sortedArrayToBST1(int[] nums,int first,int last,TreeNode node){
//当末端值小于起始值,区间无值,赋值为null,结束递归
if(first>last) {
node =null;
return node;
}
//获取中值
int mid = first + (last-first)/2;
//赋值
node.val = nums[mid];
//同理
if(first>mid-1) node.left = null;
else{
node.left = new TreeNode();
sortedArrayToBST1(nums,first,mid-1,node.left);
}
if(mid+1>last) node.right = null;
else{
node.right = new TreeNode();
sortedArrayToBST1(nums,mid+1,last,node.right);
}
return node;
}
}
6. 学习收获,官方一如既往的妙啊
方法一:中序遍历,总是选择中间位置左边的数字作为根节点
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
//调用方法,方法会放回一个根节点
return helper(nums, 0, nums.length - 1);
}
public TreeNode helper(int[] nums, int left, int right) {
//递归出口,左值大于右值
if (left > right) {
return null;
}
// 总是选择中间位置左边的数字作为根节点
int mid = (left + right) / 2;
TreeNode root = new TreeNode(nums[mid]);
root.left = helper(nums, left, mid - 1);
root.right = helper(nums, mid + 1, right);
return root;
}
}
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/solution/jiang-you-xu-shu-zu-zhuan-huan-wei-er-cha-sou-s-33/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
首先,人家代码比我少!就比我的简洁,而不是那么长的一串。
其次,人家参数比我少了一个树节点类,而返回类型和我一样,这就是我算法还有存在优化的地方,为什么我会又用返回节点类型又传节点就是因为我一开始是没有返回类型,后来做着做着觉得应该有返回类型才行。才改的。
第三,加了注释才发现,人家的代码才是yyds,无敌!又简短又能让人准确的得知具体的思路。
7 题目来源
几天没写算法,思路都不简洁了!实习,也要努力啊,不然会被吃掉的哦,加油加油。另外,挤地铁太难了! ------swrici