Leetcode __108. 将有序数组转换为二叉搜索树

问题描述

将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1

示例:
给定有序数组: [-10,-3,0,5,9],
一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:

      0
     / \
   -3   9
   /   /
 -10  5

思路

先理解几个概念:
平衡二叉树:是一种二叉排序树,其中每一个节点的左子树和右子树的高度差至多等于1.
二叉搜索树:(二叉排序树)又称二叉查找树,它或者是一棵空树,或者具有一下性质的二叉树

  • 若它的左子树不空,则左子树上的所有节点的值均小于它的根节点的值
  • 若它的右子树不空,则右子树上的所有节点的值均大于它根节点的值
  • 它的左右子树也分别为二叉排序树
    当对一棵二叉搜索数进行中序遍历的时候,就可以得到一个有序的序列,这样的数称为二叉排序或搜索树
    构造一棵二叉排序或搜索树的目的,并不是为了排序,而是为了提高查找和插入删除关键字的速度。

从概念中可以理解出:有序序列的中间值即为根节点,左右两边数组各自成二叉搜索树,递归是最简单的实现方式

实现

/**
 1. Definition for a binary tree node.
 2. public class TreeNode {
 3.     int val;
 4.     TreeNode left;
 5.     TreeNode right;
 6.     TreeNode(int x) { val = x; }
 7. }
 */
class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        if (nums == null || nums.length == 0) {
            return null;
        }
        return creatSub(nums, 0, nums.length-1);
    }
     private static TreeNode creatSub(int[] nums,int start,int end){
        int len = nums.length;
        if (start > end) {
            return null;
        }
        int rootnum = (start + end) / 2;
        TreeNode root = new TreeNode(nums[rootnum]);//注意是中间是数组的值,不是排序位置
        root.left = creatSub(nums, start, rootnum-1);//递归,要传入变量值
        root.right = creatSub(nums, rootnum + 1, end);
        return root;
    }
}

犯错

  1. 在递归时候思路还停留在循环中,思路不清晰;
  2. 边界值处理不好,第一次传入从0开始到长度-1结束,若不-1,则越界;
  3. 创建根节点时候,要传入的 是中间数组的值,不是位置;
  4. 递归要传入变量,不能是具体的值;
  5. 每次递归调用子方法的时候,要把中间值根节点的值去掉,故rootnum-1,rootnum+1

实现2(不推荐)

从思路中我们知道,每次把中间根节点抛开,左右两边各自数组再递归调用函数即可,但这其中要复制数组,占用空间较多,比较慢,

/**
 * 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){
        if (nums == null || nums.length == 0) {
            return null;
        }

        int len = nums.length;
        TreeNode root = new TreeNode(nums[len / 2]);
        int[] leftnum = new int[len / 2];
        int[] rightnum =new int[len - len / 2 - 1];
        System.arraycopy(nums,0,leftnum,0,len/2);
        System.arraycopy(nums,len/2+1,rightnum,0,len - len / 2 - 1);

        root.left = sortedArrayToBST(leftnum);
        root.right = sortedArrayToBST(rightnum);
        return root;

    }
}

这里copy数组时候用了native方法,可以比赋值数组快一些

小结

本问题考察的就是二分查找,每次取中间值,再对各自边数组递归,但不一样的是,取的中间值,是中间数组的值,记住这点即可。

猜你喜欢

转载自blog.csdn.net/Growing_way/article/details/82682511