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

题目

给定一个单链表的头节点 head ,其中的元素 按升序排序 ,将其转换为高度平衡的二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点的左右两个子树的高度差不超过 1。

示例 1:
[中等] 109. 有序链表转换二叉搜索树 - 图1

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

解答 & 代码

递归分治:将链表区间 [head, tail) 构建为二叉搜索树

  1. 找到中间节点 mid:快慢指针法
  2. 根据中间节点 mid 的值建立二叉搜索树的根节点 root
  3. 递归将左半边链表构建为二叉搜索树,作为根节点 root 的左子树,即 root->left = dfsBuildTree(head, mid)
  4. 递归将右半边链表构建为二叉搜索树,作为根节点 root 的右子树,即 root->right = dfsBuildTree(mid->next, tail)
  5. 返回根节点 root

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * ListNode *next;
    6. * ListNode() : val(0), next(nullptr) {}
    7. * ListNode(int x) : val(x), next(nullptr) {}
    8. * ListNode(int x, ListNode *next) : val(x), next(next) {}
    9. * };
    10. */
    11. /**
    12. * Definition for a binary tree node.
    13. * struct TreeNode {
    14. * int val;
    15. * TreeNode *left;
    16. * TreeNode *right;
    17. * TreeNode() : val(0), left(nullptr), right(nullptr) {}
    18. * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    19. * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
    20. * };
    21. */
    22. class Solution {
    23. // 快慢指针法查找链表中间节点,并返回
    24. ListNode* findMidNode(ListNode* head, ListNode* tail)
    25. {
    26. ListNode* slow = head;
    27. ListNode* fast = head;
    28. while(fast != tail && fast->next != tail)
    29. {
    30. slow = slow->next;
    31. fast = fast->next->next;
    32. }
    33. return slow;
    34. }
    35. // 递归分治,将链表区间 [head, tail) 构建为二叉搜索树
    36. TreeNode* dfsBuildTree(ListNode* head, ListNode* tail)
    37. {
    38. // 递归结束条件:区间为空,直接返回空节点
    39. if(head == tail)
    40. return nullptr;
    41. // 1. 找到链表中间节点
    42. ListNode* mid = findMidNode(head, tail);
    43. // 2. 建立根节点
    44. TreeNode* root = new TreeNode(mid->val);
    45. // 3. 递归将左半边链表构建为二叉搜索树,作为根节点 root 的左子树
    46. root->left = dfsBuildTree(head, mid);
    47. // 4. 递归将右半边链表构建为二叉搜索树,作为根节点 root 的右子树
    48. root->right = dfsBuildTree(mid->next, tail);
    49. // 5. 返回根节点 root
    50. return root;
    51. }
    52. public:
    53. TreeNode* sortedListToBST(ListNode* head) {
    54. return dfsBuildTree(head, nullptr);
    55. }
    56. };

    复杂度分析:设链表长为 N

  • 时间复杂度 O(N logN):递归每个深度存在 2 个区间,空间复杂度 O(2logN),每个区间查找中间节点时间复杂度 O(N)
  • 空间复杂度 O(logN):递归栈深度

执行结果:

  1. 执行结果:通过
  2. 执行用时:28 ms, 在所有 C++ 提交中击败了 40.35% 的用户
  3. 内存消耗:27.5 MB, 在所有 C++ 提交中击败了 91.84% 的用户