题目:将升序数组转化为平衡二叉搜索树

描述:给出一个升序排序的数组,将其转化为平衡二叉搜索树(BST).

示例1:输入:[-1,0,1,2],返回值:{1,0,2,-1}

解法一:

思路分析:二叉搜索树,又称之为二叉排序树(二叉查找树),它是一棵空树,或者是具有以下性质的二叉树:

若它的左子树不为空,则左子树上所有节点的值都小于根节点的值

若它的右子树不为空,则右子树上所有节点的值都大于根节点的值

它的左右子树也分别是二叉搜索树。

平衡二叉搜索树为:保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均查找长度。该树的性质是:左子树与右子树高度之差的绝对值不超过1,树的每一个节点都有一个平衡因子,任一节点的平衡因子是-1、0、1(每一个节点的平衡因子 = 右子树高度 - 左子树高度)

本题给出的是升序序列的有序数组,故可以保证数组是二叉搜索树中的中序遍历,我们首先应该确定二叉搜索树的根节点,然后其余数字分别位于平衡二叉树的左子树和右子树之中,当然左右子树也必须满足AVL,故可以通过递归的方式创建AVL树。

实例分析:[-1,0,1,2],设置左右值,l和r,取中间变量为m,方便进行判断。

数组

-1

0

1

2

首先以-1为根节点,其不满足平均分配

以0为根节点

0

-1

1

2

不满足分配规则,以1为根节点

1

0

2

-1

满足分配规则,将其输出。

具体java代码如下所示:


import java.util.*;
 
/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */
 
public class Solution {
    /**
     *
     * @param num int整型一维数组
     * @return TreeNode类
     */
    TreeNode convert(int num[], int l, int r) {
        if (l >= r)
            return null;
        int m = (l + r) / 2;//平均分配
        TreeNode left = convert(num, l, m);//判断左子树为……
        TreeNode root = new TreeNode(num[m]);//确定根节点
        TreeNode right = convert(num, m + 1, r);
        root.left = left;
        root.right = right;
        return root;
    }
    public TreeNode sortedArrayToBST(int[] num) {
        return convert(num, 0, num.length);
    }
}


因为要递归遍历两层,第一层为确定根结点,第二层为判断是否符合条件,所以,其时间复杂度为O(N),空间复杂度为O(1)。

解法二:

思路分析:为了降低时间,我们可以将数组从中点分成左右两份,用左侧的数字构建左子树,右侧的数字构建右子树,递归执行,直到数组长度为0。则可以保证树中任意节点的左子树高度和右子树高度最多相差1。

具体Java代码如下所示: 

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

public class Solution {
    /**
     * 
     * @param num int整型一维数组 
     * @return TreeNode类
     */
    public TreeNode sortedArrayToBST (int[] num) {
        // write code here
        if(num == null || num.length == 0){
            return null;
        }
        int n = num.length;
        int mid = n/2;
        TreeNode node = new TreeNode(num[mid]);//将从中点开始进行判断
        int []numLeft = new int [mid];//中点左边为左子树
        int []numRight = new int [n-mid-1];//中点右边为右子树
        for(int i = 0 ; i<mid ; i++){//将左边的元素放进去
            numLeft[i] = num[i];
        }
        for(int i = mid+1 ; i<n ; i++){//将右边的元素放进去
            numRight[i-mid-1] = num[i];
        }
        node.left = sortedArrayToBST(numLeft);//循环遍历
        node.right = sortedArrayToBST(numRight);
        return node;
    }
}

因为要分别构建左右子树,并且需要循环判断左右子树的高度差值,所以时间复杂度为O(N),空间复杂度为O(N)。