力扣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,null,3] 和 [3,1] 都是高度平衡二叉搜索树。

提示:

1 <= nums.length <= 104

-104 <= nums[i] <= 104 nums 按 严格递增 顺序排列
方法一 :中序遍历,总是选择中间位置左边的数字作为根节点 选择中间位置左边的数字作为根节点,则根节点的下标为

mid=(left+right)/2\textit{mid}=(\textit{left}+\textit{right})/2mid=(left+right)/2,此处的除法为整数除法。

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return HeightBalenced(nums,0,nums.length - 1);
    }
    public TreeNode HeightBalenced(int[] nums, int left, int right){
        if(left > right){
            return null;
        }
        //总是选择中间位置左边的数字作为根节点
        int mid = (left + right) / 2;

        TreeNode root = new TreeNode(nums[mid]);
        root.left = HeightBalenced(nums,left,mid - 1);
        root.right = HeightBalenced(nums,mid + 1,right);
        return root;
    }
}

复杂度分析

时间复杂度:O(n),其中 n是数组的长度。每个数字只访问一次。

空间复杂度:O(log⁡n),其中 n 是数组的长度。空间复杂度不考虑返回值,因此空间复杂度主要取决于递归栈的深度,递归栈的深度是 O(log⁡n)。

方法二 :中序遍历,总是选择中间位置右边的数字作为根节点

选择中间位置右边的数字作为根节点,则根节点的下标为 mid=(left+right+1)/2\textit{mid}=(\textit{left}+\textit{right}+1)/2mid=(left+right+1)/2,此处的除法为整数除法。

java 复制代码
class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return helper(nums, 0, nums.length - 1);
    }

    public TreeNode helper(int[] nums, int left, int right) {
        if (left > right) {
            return null;
        }

        // 总是选择中间位置右边的数字作为根节点
        int mid = (left + right + 1) / 2;

        TreeNode root = new TreeNode(nums[mid]);
        root.left = helper(nums, left, mid - 1);
        root.right = helper(nums, mid + 1, right);
        return root;
    }
}

复杂度分析

时间复杂度:O(n),其中 n 是数组的长度。每个数字只访问一次。

空间复杂度:O(log⁡n),其中 n 是数组的长度。空间复杂度不考虑返回值,因此空间复杂度主要取决于递归栈的深度,递归栈的深度是 O(log⁡n)

方法三 :中序遍历,选择任意一个中间位置数字作为根节点

选择任意一个中间位置数字作为根节点,则根节点的下标为 mid=(left+right)/2\textit{mid}=(\textit{left}+\textit{right})/2mid=(left+right)/2 和 mid=(left+right+1)/2\textit{mid}=(\textit{left}+\textit{right}+1)/2mid=(left+right+1)/2 两者中随机选择一个,此处的除法为整数除法。

java 复制代码
class Solution {
    Random rand = new Random();

    public TreeNode sortedArrayToBST(int[] nums) {
        return helper(nums, 0, nums.length - 1);
    }

    public TreeNode helper(int[] nums, int left, int right) {
        if (left > right) {
            return null;
        }

        // 选择任意一个中间位置数字作为根节点
        int mid = (left + right + rand.nextInt(2)) / 2;

        TreeNode root = new TreeNode(nums[mid]);
        root.left = helper(nums, left, mid - 1);
        root.right = helper(nums, mid + 1, right);
        return root;
    }
}

复杂度分析

时间复杂度:O(n),其中 n 是数组的长度。每个数字只访问一次。

空间复杂度:O(log⁡n),其中 n 是数组的长度。空间复杂度不考虑返回值,因此空间复杂度主要取决于递归栈的深度,递归栈的深度是 O(log⁡n)

相关推荐
naruto_lnq37 分钟前
分布式系统安全通信
开发语言·c++·算法
Jasmine_llq1 小时前
《P3157 [CQOI2011] 动态逆序对》
算法·cdq 分治·动态问题静态化+双向偏序统计·树状数组(高效统计元素大小关系·排序算法(预处理偏序和时间戳)·前缀和(合并单个贡献为总逆序对·动态问题静态化
爱吃rabbit的mq2 小时前
第09章:随机森林:集成学习的威力
算法·随机森林·集成学习
(❁´◡`❁)Jimmy(❁´◡`❁)2 小时前
Exgcd 学习笔记
笔记·学习·算法
YYuCChi3 小时前
代码随想录算法训练营第三十七天 | 52.携带研究材料(卡码网)、518.零钱兑换||、377.组合总和IV、57.爬楼梯(卡码网)
算法·动态规划
不能隔夜的咖喱3 小时前
牛客网刷题(2)
java·开发语言·算法
VT.馒头3 小时前
【力扣】2721. 并行执行异步函数
前端·javascript·算法·leetcode·typescript
进击的小头3 小时前
实战案例:51单片机低功耗场景下的简易滤波实现
c语言·单片机·算法·51单片机
咖丨喱5 小时前
IP校验和算法解析与实现
网络·tcp/ip·算法
罗湖老棍子5 小时前
括号配对(信息学奥赛一本通- P1572)
算法·动态规划·区间dp·字符串匹配·区间动态规划