题目描述
解题思路
二叉搜索树,利用其性质,使用中序遍历即可。
本文解法基于性质:二叉搜索树的中序遍历为 递增序列 。
将 二叉搜索树 转换成一个 “排序的循环双向链表” ,其中包含三个要素:
- 排序链表: 节点应从小到大排序,因此应使用 中序遍历 “从小到大”访问树的节点。
 - 双向链表: 在构建相邻节点的引用关系时,设前驱节点 pre 和当前节点 cur ,不仅应构建 pre.right = cur ,也应构建 cur.left = pre 。
 - 循环链表: 设链表头节点 head 和尾节点 tail ,则应构建 head.left = tail 和 tail.right = head
 

算法流程:
dfs(cur): 递归法中序遍历;
- 终止条件: 当节点 cur 为空,代表越过叶节点,直接返回;
 - 递归左子树,即 dfs(cur.left) ;
 - 构建链表:
- 当 pre 为空时: 代表正在访问链表头节点,记为 head ;
 - 当 pre 不为空时: 修改双向节点引用,即 pre.right = cur , cur.left = pre ;
 - 保存 cur : 更新 pre = cur ,即节点 cur 是后继节点的 pre ;
 
 - 递归右子树,即 dfs(cur.right) ;
 
treeToDoublyList(root):
- 特例处理: 若节点 root 为空,则直接返回;
 - 初始化: 空节点 pre ;
 - 转化为双向链表: 调用 dfs(root) ;
 - 构建循环链表: 中序遍历完成后,head 指向头节点, pre 指向尾节点,因此修改 head 和 pre 的双向节点引用即可;
 返回值: 返回链表的头节点 head 即可;
class Solution {public Node treeToDoublyList(Node root) {if (root == null) {return head;}dfs(root);// 形成双向链表head.right = pre;pre.left = head;return head;}Node pre;Node head;public void dfs(Node cur) {if (cur == null) {return;}// 中序遍历dfs(cur.left);if (pre == null) head = pre; // 此时是头节点// 交换指向else pre.right = cur;cur.left = pre;pre = cur;dfs(cur.right);}}
时间复杂度 O(N) : N 为二叉树的节点数,中序遍历需要访问所有节点。
空间复杂度 O(N) : 最差情况下,即树退化为链表时,递归深度达到 N,系统使用 O(N) 栈空间。
