前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >图解精选 TOP 面试题 004 | LeetCode 108. 将有序数组转换为二叉搜索树

图解精选 TOP 面试题 004 | LeetCode 108. 将有序数组转换为二叉搜索树

作者头像
江不知
发布2019-12-19 15:41:38
8860
发布2019-12-19 15:41:38
举报
文章被收录于专栏:编程拯救世界

该系列题目取自 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],它可以表示下面这个高度平衡二叉搜索树:

代码语言:javascript
复制
      0
     / \
   -3   9
   /   /
 -10  5

解题思路

题目给出了一个升序排序的有序数组,要求我们转换为一棵高度平衡二叉搜索树

在此之前,我们先来回忆一下什么是二叉搜索树。

二叉搜索树

二叉搜索树[1](Binary Search Tree)是指一棵空树或具有如下性质的二叉树:

  1. 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值
  2. 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值
  3. 任意节点的左、右子树也分别为二叉搜索树
  4. 没有键值相等的节点

基于以上性质,我们可以得出一个二叉搜索树的特性:二叉搜索树的中序遍历结果为递增序列

那么现在题目给了我们一个递增序列,要求我们构造一棵二叉搜索树,就是要我们实现这一特性的逆过程

还记得什么是中序遍历吗?中序遍历的顺序为:左节点 根节点 右节点。这个遍历过程可以使用递归非常直观地进行表示。

如何构造树

构造一棵树的过程可以拆分成无数个这样的子问题:构造树的每个节点以及节点之间的关系。对于每个节点来说,都需要:

  1. 选取节点
  2. 构造该节点的左子树
  3. 构造该节点的右子树

因题目要求构造一棵「高度平衡」的树,所以我们在选取节点时选择数组的中点作为根节点,以此来保证平衡性。

以题目给出的 [-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 作为根节点。

最终构造结果如下:

递归设计

函数作用

通过上述解题过程我们可以明确该问题的子问题是:构造树的每个节点以及该节点的左右子树。因此,递归函数的作用很明显:

  1. 选取要构造关系的节点并创建它
  2. 构造该节点的左子树
  3. 构造该节点的右子树

函数的输入为递增数组,函数的返回为完成构造的节点

何时结束

当输入的递增数组为空时,只能构成一棵空树,此时返回空节点。

何时调用

当构造节点的左右子树时,对递增数组进行拆分并进行递归调用。

具体实现

Python

代码语言:javascript
复制
# 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

Go

代码语言:javascript
复制
/**
 * 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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-12-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程拯救世界 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目描述
  • 解题思路
    • 二叉搜索树
      • 如何构造树
      • 递归设计
        • 函数作用
          • 何时结束
            • 何时调用
            • 具体实现
              • Python
                • Go
                • 复杂度
                • 总结
                  • 参考资料
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档