leetcode:109. 有序链表转换二叉搜索树
题目
给定一个单链表的头节点 head ,其中的元素 按升序排序 ,将其转换为高度平衡的二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点的左右两个子树的高度差不超过 1。
示例 1:![[中等] 109. 有序链表转换二叉搜索树 - 图1](/uploads/projects/liangduo-rjrcs@ggu4wq/6a3a3801c645f6702b7d60284c0592db.jpeg)
输入: head = [-10,-3,0,5,9]输出: [0,-3,9,-10,null,5]解释: 一个可能的答案是[0,-3,9,-10,null,5],它表示所示的高度平衡的二叉搜索树。
输入: head = []输出: []
解答 & 代码
递归分治:将链表区间 [head, tail) 构建为二叉搜索树
- 找到中间节点
mid:快慢指针法 - 根据中间节点
mid的值建立二叉搜索树的根节点root - 递归将左半边链表构建为二叉搜索树,作为根节点
root的左子树,即root->left = dfsBuildTree(head, mid) - 递归将右半边链表构建为二叉搜索树,作为根节点
root的右子树,即root->right = dfsBuildTree(mid->next, tail) 返回根节点
root/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(next) {}* };*//*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/class Solution {// 快慢指针法查找链表中间节点,并返回ListNode* findMidNode(ListNode* head, ListNode* tail){ListNode* slow = head;ListNode* fast = head;while(fast != tail && fast->next != tail){slow = slow->next;fast = fast->next->next;}return slow;}// 递归分治,将链表区间 [head, tail) 构建为二叉搜索树TreeNode* dfsBuildTree(ListNode* head, ListNode* tail){// 递归结束条件:区间为空,直接返回空节点if(head == tail)return nullptr;// 1. 找到链表中间节点ListNode* mid = findMidNode(head, tail);// 2. 建立根节点TreeNode* root = new TreeNode(mid->val);// 3. 递归将左半边链表构建为二叉搜索树,作为根节点 root 的左子树root->left = dfsBuildTree(head, mid);// 4. 递归将右半边链表构建为二叉搜索树,作为根节点 root 的右子树root->right = dfsBuildTree(mid->next, tail);// 5. 返回根节点 rootreturn root;}public:TreeNode* sortedListToBST(ListNode* head) {return dfsBuildTree(head, nullptr);}};
复杂度分析:设链表长为 N
- 时间复杂度 O(N logN):递归每个深度存在 2 个区间,空间复杂度 O(2logN),每个区间查找中间节点时间复杂度 O(N)
- 空间复杂度 O(logN):递归栈深度
执行结果:
执行结果:通过执行用时:28 ms, 在所有 C++ 提交中击败了 40.35% 的用户内存消耗:27.5 MB, 在所有 C++ 提交中击败了 91.84% 的用户
