leetcode 链接:剑指 Offer 36. 二叉搜索树与双向链表

题目

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。

为了让您更好地理解问题,以下面的二叉搜索树为例:
[中等] 剑指 Offer 36. 二叉搜索树与双向链表 - 图1
我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。
[中等] 剑指 Offer 36. 二叉搜索树与双向链表 - 图2
特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。

解答 & 代码

  • 初始化 pre 节点为 NULL,代表中序遍历的前一个节点
  • 递归中序遍历将二叉搜索树转换为双向链表
    • 递归结束条件:当前节点为空,直接返回
    • 递归遍历左子树
    • 处理当前节点(root
      • 如果 pre 为空,代表当前节点是最小元素节点,即转换后双向链表的 head 节点,另 head = root
      • 如果 pre 不为空,将 preright 指针指向当前节点
      • 将当前节点的 left 指针指向 pre
      • 更新 pre = root
    • 递归遍历右子树
  • 将双向链表的头尾节点也双向链接

    1. /*
    2. // Definition for a Node.
    3. class Node {
    4. public:
    5. int val;
    6. Node* left;
    7. Node* right;
    8. Node() {}
    9. Node(int _val) {
    10. val = _val;
    11. left = NULL;
    12. right = NULL;
    13. }
    14. Node(int _val, Node* _left, Node* _right) {
    15. val = _val;
    16. left = _left;
    17. right = _right;
    18. }
    19. };
    20. */
    21. class Solution {
    22. private:
    23. Node* pre; // 中序遍历的前一个节点
    24. Node* head; // 头节点
    25. // 递归中序遍历将二叉搜索树转换为双向链表
    26. void inOrderTreeToList(Node* root)
    27. {
    28. // 递归结束条件
    29. if(root == NULL)
    30. return;
    31. // 递归中序遍历左子树
    32. inOrderTreeToList(root->left);
    33. // 处理当前节点
    34. // 如果 pre 不为空,则将 pre 的 right 指针指向当前节点
    35. if(pre != NULL)
    36. pre->right = root;
    37. // 如果 pre 为空,说明当前节点是转换后链表的 head 节点(最小元素节点)
    38. else
    39. head = root;
    40. root->left = pre; // 将当前节点的 left 指针指向 pre
    41. pre = root; // 更新 pre
    42. // 递归中序遍历右子树
    43. inOrderTreeToList(root->right);
    44. }
    45. public:
    46. Node* treeToDoublyList(Node* root) {
    47. if(root == NULL)
    48. return NULL;
    49. pre = NULL; // 将中序遍历的前一个节点初始化为空
    50. head = NULL; // 头节点
    51. inOrderTreeToList(root); // 中序遍历将二叉搜索树转换为双向链表
    52. // 将双向链表的头尾节点双向连接
    53. head->left = pre;
    54. pre->right = head;
    55. return head;
    56. }
    57. };

    执行结果: ``` 执行结果:通过

执行用时:4 ms, 在所有 C++ 提交中击败了 93.00% 的用户 内存消耗:7.4 MB, 在所有 C++ 提交中击败了 58.54% 的用户 ```