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

426 阅读3分钟

这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战

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

问题描述

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

给定一个升序排序的数组,将其转化为平衡二叉搜索树(BST)。平衡二叉搜索树是指树上的每个节点 node 都满足左子树中所有节点的的值都小于 node 的值,右子树中所有节点的值都大于 node 的值,并且左右子树的节点数量之差不大于1。

示例:

输入:nums = [-10,-3,0,5,9]

输出:[0,-3,9,-10,null,5]

image-20211112144832249

分析问题

我们都知道对一颗二叉搜索树进行中序遍历,得到的序列是一个升序排列的。所以给定的数组是二叉搜索树的中序遍历结果。下面我们来看一下如何根据二叉搜索树的中序遍历来生成一颗高度平衡的二叉搜索树。

因为平衡二叉搜索树的左、右子树的节点数量之差不大于1。所以,我们可以选择数组中中间的数字作为二叉搜索树的根节点。这样就可以确保左右子树的节点个数之差不大于1,从而使得树时平衡的。如果给定的数组长度是奇数,则根节点的选择是唯一的,如果数组的长度是偶数,则可以选择中间位置左边的数字作为根节点或者选择中间位置右边的数字作为根节点,选择不同的数字作为根节点则创建的平衡二叉搜索树也是不同的。

在确定了平衡二叉搜索树的根节点之后,其余的数字分别位于平衡二叉搜索树的左子树和右子树中,左子树和右子树分别也是平衡二叉搜索树,因此可以通过递归的方式创建平衡二叉搜索树。

根据选择根节点的不同,我们可以有三种方法来构造平衡二叉搜索树。

方法一

选择中间位置左边的数字作为根节点,则根节点的下标为 mid=(left+right) // 2。

image-20211112154111091

class Solution:
    def sortedArrayToBST(self, nums):
        
        def cur(left, right):
            if left > right:
                return None

            #选择中间位置左边的数字作为根节点
            mid = (left + right) // 2
            root = TreeNode(nums[mid])
            #递归求解左右子树
            root.left = cur(left, mid - 1)
            root.right = cur(mid + 1, right)
            return root

        return cur(0, len(nums) - 1)

方法二:

选择中间位置右边的数字作为根节点,则根节点的下标为 mid=(left+right+1) // 2。

image-20211112154514910

class Solution:
    def sortedArrayToBST(self, nums):

        def cur(left, right):
            if left > right:
                return None

            #选择中间位置右边的数字作为根节点
            mid = (left + right + 1) // 2
            root = TreeNode(nums[mid])
            #递归求解左右子树
            root.left = cur(left, mid - 1)
            root.right = cur(mid + 1, right)
            return root

        return cur(0, len(nums) - 1)

方法三

选择任意一个中间位置数字作为根节点,则根节点的下标mid在(left+right)//2 和 (left+right+1)/2 中随机选择一个。

import random
class Solution:
    def sortedArrayToBST(self, nums):

        def cur(left, right):
            if left > right:
                return None

            #选择中间位置随机一个作为根节点
            random_data= random.randint(0, 1)
            mid = (left + right + random_data) // 2
            root = TreeNode(nums[mid])
            #递归求解左右子树
            root.left = cur(left, mid - 1)
            root.right = cur(mid + 1, right)
            return root

        return cur(0, len(nums) - 1)