LeetCode精选Top面试题之将有序数组转换为二叉搜索树

522 阅读4分钟

这是我参与更文挑战的第8天,活动详情查看: 更文挑战

前言

公众号给npy的前端秘籍

加vx👉16639199716,拉你进群嗷~❤️

今天继续学习LeetCode精选面试题,今天选择第108题进行学习与总结~

题目描述

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。

高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。

示例1

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

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

解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案。

示例2

输入:nums = [1,3]

输出:[3,1]

解释:[1,3] 和 [3,1] 都是高度平衡二叉搜索树。

先来个饭甜品

二叉查找树:

二叉查找树就是左结点小于根节点,右结点大于根节点的一种排序树,也叫二叉搜索树。也叫BST,英文Binary Sort Tree。

二叉查找树比普通树查找更快,查找、插入、删除的时间复杂度为O(logN)。但是二叉查找树有一种极端的情况,就是会变成一种线性链表似的结构。此时时间复杂度就变味了O(N),为了解决这种情况,出现了二叉平衡树。

平衡二叉树:

平衡二叉树全称平衡二叉搜索树,也叫AVL树。是一种自平衡的树。

AVL树也规定了左结点小于根节点,右结点大于根节点。并且还规定了左子树和右子树的高度差不得超过1。这样保证了它不会成为线性的链表。AVL树的查找稳定,查找、插入、删除的时间复杂度都为O(logN),但是由于要维持自身的平衡,所以进行插入和删除结点操作的时候,需要对结点进行频繁的旋转。

解题思路:

题目要求构建高度平衡二叉搜索树,找到解决问题的突破口。

  1. 将有序数组一分为二,中间结点成为根结点,前半部分是左子树,右半部分是右子树;
  2. 递归构建左子树和右子树,应用到分治思想。

什么是分而治之呢?

  • 分而治之是算法设计中的一种方法
  • 它将一个问题分成多个和原问题相似的小问题,递归解决小问题,再将结果合并以解决原来的问题

构建一棵树包括:

  1. 构建 root、构建 root.left 和 root.right
  2. 题目要求“高度平衡”——构建 root 时,选数组的中间元素作为 root 节点值,即可保证平衡
  3. 递归函数的可以传数组,也可以传指针,前者每次都要切割数组,我选择指针:start、end,分别代表参与构建BST的数组的首尾索引。
const buildBST = (nums, start, end) => {
    if (start > end) { // 构成不了区间,返回null
      return null;
    }

    const midIndex = (start + end) >>> 1; // 求中间索引
    const root = new TreeNode(nums[midIndex]); // 构建当前节点

    root.left = buildBST(nums, start, midIndex - 1); // 构建左子树
    root.right = buildBST(nums, midIndex + 1, end); // 构建右子树

    return root;
};
var sortedArrayToBST = function(nums) {
    return buildBST(nums, 0, nums.length - 1); // 递归的入口
};
//时间复杂度:用O(1)的时间找到数组中间的元素,每个元素都被遍历到,所以是O(n)
//空间复杂度:递归占用的栈空间:O(logn)

总结

刷题打卡第14天,选择力扣第108题,学习了有序数组转换为二叉搜索树,一起加油哇~

❤️ 感谢大家

如果你觉得这篇内容对你挺有有帮助的话: 点赞支持下吧,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓 -_-)关注公众号给npy的前端秘籍,我们一起学习一起进步。 觉得不错的话,也可以阅读其他文章(感谢朋友的鼓励与支持🌹🌹🌹)

开启LeetCode之旅

LeetCode之双指针

Leet27、移除元素

前端工程师必学的经典排序算法

LeetCode20、括号匹配

LeetCode7、整数反转