该系列题目取自 LeetCode 精选 TOP 面试题列表:https://leetcode-cn.com/problemset/top/
原题链接:https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/
将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点的左右两个子树的高度差的绝对值不超过 1。
示例:
给定有序数组: [-10,-3,0,5,9]
,
一个可能的答案是:[0,-3,9,-10,null,5]
,它可以表示下面这个高度平衡二叉搜索树:
0
/ \
-3 9
/ /
-10 5
题目给出了一个升序排序的有序数组,要求我们转换为一棵高度平衡二叉搜索树。
在此之前,我们先来回忆一下什么是二叉搜索树。
二叉搜索树[1](Binary Search Tree)是指一棵空树或具有如下性质的二叉树:
基于以上性质,我们可以得出一个二叉搜索树的特性:二叉搜索树的中序遍历结果为递增序列。
那么现在题目给了我们一个递增序列,要求我们构造一棵二叉搜索树,就是要我们实现这一特性的逆过程。
还记得什么是中序遍历吗?中序遍历的顺序为:左节点 根节点 右节点。这个遍历过程可以使用递归非常直观地进行表示。
构造一棵树的过程可以拆分成无数个这样的子问题:构造树的每个节点以及节点之间的关系。对于每个节点来说,都需要:
因题目要求构造一棵「高度平衡」的树,所以我们在选取节点时选择数组的中点作为根节点,以此来保证平衡性。
以题目给出的 [-10,-3,0,5,9]
为例。
我们选取数组中点,即数字 0 作为根节点。此时,以 0 为分界点将数组分为左右两个部分,左侧为 [-10, -3]
,右侧为 [5, 9]
。因该数组为升序排列的有序数组,所以左侧数组值均小于 0,可作为节点 0 的左子树;右侧数组值均大于 0,可作为节点 0 的右子树。
同上述步骤,将 [-10, -3]
和 [5, 9]
单独看作两棵树,从而继续为他们构造左右子树。
对于左侧数组 [-10, -3]
,我们选取 -3 作为根节点;对于右侧数组 [5, 9]
,选取 9 作为根节点。
最终构造结果如下:
通过上述解题过程我们可以明确该问题的子问题是:构造树的每个节点以及该节点的左右子树。因此,递归函数的作用很明显:
函数的输入为递增数组,函数的返回为完成构造的节点。
当输入的递增数组为空时,只能构成一棵空树,此时返回空节点。
当构造节点的左右子树时,对递增数组进行拆分并进行递归调用。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
if not nums:
return None
# 找到中点作为根节点
mid = len(nums) // 2
node = TreeNode(nums[mid])
# 左侧数组作为左子树
left = nums[:mid]
right = nums[mid+1:]
# 递归调用
node.left = self.sortedArrayToBST(left)
node.right = self.sortedArrayToBST(right)
return node
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func sortedArrayToBST(nums []int) *TreeNode {
if len(nums) == 0 {
return nil
}
mid := len(nums) / 2
left := nums[:mid]
right := nums[mid+1:]
node := &TreeNode{nums[mid], sortedArrayToBST(left), sortedArrayToBST(right)}
return node
}
[1]
二叉搜索树: https://zh.wikipedia.org/wiki/%E4%BA%8C%E5%85%83%E6%90%9C%E5%B0%8B%E6%A8%B9