☆打卡算法☆LeetCode 109、有序链表转换二叉搜索树 算法解析

简介: “给定单链表头结点,其中元素升序排序,将其转换为高度平衡的二叉搜索树。”

一、题目


1、算法题目

“给定单链表头结点,其中元素升序排序,将其转换为高度平衡的二叉搜索树。”

题目链接:

来源:力扣(LeetCode)

链接:109. 有序链表转换二叉搜索树


2、题目描述

给定一个单链表的头节点  head ,其中的元素 按升序排序 ,将其转换为高度平衡的二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差不超过 1。

网络异常,图片无法展示
|

示例 1:
输入: head = [-10,-3,0,5,9]
输出: [0,-3,9,-10,null,5]
解释: 一个可能的答案是[0,-3,9,-10,null,5],它表示所示的高度平衡的二叉搜索树。
复制代码
示例 2:
输入: head = []
输出: []
复制代码


二、解题


1、思路分析

这道题跟108题类似,第一步都是需要确定根节点,也就是让左右子树的节点个数尽可能接近,这样左右子树的高度就会相近。

这样的根节点被称为中位数,如果链表的元素个数为奇数,那么中间值就位中位数,如果元素个数为偶数,那么两个中间值都可以作为中位数。

根据中位数的性质,可以使用分治的思路,递归地对左右子树进行构造,找出对应的中位数作为根节点,这样得到的二叉搜索树就是平衡的。


2、代码实现

代码参考:

class Solution {
    public TreeNode sortedListToBST(ListNode head) {
        return buildTree(head, null);
    }
    public TreeNode buildTree(ListNode left, ListNode right) {
        if (left == right) {
            return null;
        }
        ListNode mid = getMedian(left, right);
        TreeNode root = new TreeNode(mid.val);
        root.left = buildTree(left, mid);
        root.right = buildTree(mid.next, right);
        return root;
    }
    public ListNode getMedian(ListNode left, ListNode right) {
        ListNode fast = left;
        ListNode slow = left;
        while (fast != right && fast.next != right) {
            fast = fast.next;
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}
复制代码

网络异常,图片无法展示
|


3、时间复杂度

时间复杂度 : O(n log n)

其中n是链表的长度。

空间复杂度: O(log n)

其中n是数组的长度,空间复杂度取决于递归栈的深度,递归栈的深度是O(log n)。


三、总结

找出链表中位数节点的方法有很多,比较简单的是使用双指针,在开始时候两个指针都指向左端点left。

然后第一个指针向右移动两次的同时第二个指针向右移动一次,直到第一个指针到达边界的时候,第二个指针对应的元素就是中位数。

找到中位数之后,将其作为当前根节点的元素,然后递归地构造其左侧部分的链表对应的左子树,以及右侧部分的链表对应的右子树。



相关文章
【力扣】-- 移除链表元素
【力扣】-- 移除链表元素
195 1
Leetcode第21题(合并两个有序链表)
这篇文章介绍了如何使用非递归和递归方法解决LeetCode第21题,即合并两个有序链表的问题。
234 0
Leetcode第21题(合并两个有序链表)
|
11月前
|
机器学习/深度学习 存储 算法
【LeetCode 热题100】347:前 K 个高频元素(详细解析)(Go语言版)
这篇文章详细解析了力扣热题 347——前 K 个高频元素的三种解法:哈希表+小顶堆、哈希表+快速排序和哈希表+桶排序。每种方法都附有清晰的思路讲解和 Go 语言代码实现。小顶堆方法时间复杂度为 O(n log k),适合处理大规模数据;快速排序方法时间复杂度为 O(n log n),适用于数据量较小的场景;桶排序方法在特定条件下能达到线性时间复杂度 O(n)。文章通过对比分析,帮助读者根据实际需求选择最优解法,并提供了完整的代码示例,是一篇非常实用的算法学习资料。
647 90
|
存储 算法
【❤️算法笔记❤️】-每日一刷-21、合并两个有序链表
【❤️算法笔记❤️】-每日一刷-21、合并两个有序链表
351 0
|
12月前
|
存储 自然语言处理 算法
【LeetCode 热题100】208:实现 Trie (前缀树)(详细解析)(Go语言版)
本文详细解析了力扣热题 208——实现 Trie(前缀树)。Trie 是一种高效的树形数据结构,用于存储和检索字符串集合。文章通过插入、查找和前缀匹配三个核心操作,结合 Go 语言实现代码,清晰展示了 Trie 的工作原理。时间复杂度为 O(m),空间复杂度也为 O(m),其中 m 为字符串长度。此外,还探讨了 Trie 的变种及应用场景,如自动补全和词典查找等。适合初学者深入了解 Trie 结构及其实际用途。
370 14
|
11月前
|
算法 Go
【LeetCode 热题100】23:合并 K 个升序链表(详细解析)(Go语言版)
本文详细解析了 LeetCode 热题 23——合并 K 个升序链表的两种解法:优先队列(最小堆)和分治合并。题目要求将多个已排序链表合并为一个升序链表。最小堆方法通过维护节点优先级快速选择最小值,;分治合并则采用归并思想两两合并链表。文章提供了 Go 语言实现代码,并对比分析两种方法的适用场景,帮助读者深入理解链表操作与算法设计。
386 10
|
存储 算法 C语言
【C语言】深入浅出:C语言链表的全面解析
链表是一种重要的基础数据结构,适用于频繁的插入和删除操作。通过本篇详细讲解了单链表、双向链表和循环链表的概念和实现,以及各类常用操作的示例代码。掌握链表的使用对于理解更复杂的数据结构和算法具有重要意义。
3804 6
LeetCode第二十四题(两两交换链表中的节点)
这篇文章介绍了LeetCode第24题的解法,即如何通过使用三个指针(preNode, curNode, curNextNode)来两两交换链表中的节点,并提供了详细的代码实现。
180 0
LeetCode第二十四题(两两交换链表中的节点)
|
索引
力扣(LeetCode)数据结构练习题(3)------链表
力扣(LeetCode)数据结构练习题(3)------链表
308 0
|
12月前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
1124 29

推荐镜像

更多
  • DNS