题目来源:https://leetcode.cn/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/
大致题意:
给定一个排序二叉树,将其按照中序遍历的结果展开为双向链表
要求在原二叉树结点上做修改,左儿子指向左侧链表节点,右儿子指向右侧链表节点
思路
可知排序二叉树的中序遍历结果为升序序列,所以该题是让我们把二叉树展开为升序链表。
该题与力扣 114. 二叉树展开为链表类似,后者是按照前序遍历展开为单链表,本题是按照中序遍历展开为双向链表,但是本质上解题思路都是一致的:
- 使用一个 pre 指针指向中序遍历的上一个节点,初始为 null;使用 head 指针指向展开后的头节点,也是中序遍历序列的第一个节点,或者说是二叉树的最左侧节点
- 按照中序遍历的规则递归遍历二叉树,先遍历左子树,左子树遍历结束后,pre 指针应指向左子树中序遍历的最后一个节点,将 pre 的右指针指向当前节点,并将当前节点的左指针指向 pre(这里需要注意,如果 pre 为空,表示当前节点是最左侧节点,应该将 head 指针指向当前节点,同时不更新 pre 的右指针和当前节点左指针)。然后更新 pre 指针指向当前节点,再遍历右子树,重复本步操作
- 遍历结束后,本题要求构建的是循环双向链表,需要处理链表的头尾节点相连
具体看代码
public Node treeToDoublyList(Node root) {
dfs(root);
// 处理头尾节点相连
if (head != null) {
head.left = pre;
pre.right = head;
}
return head;
}
public void dfs(Node node) {
if (node == null) {
return;
}
// 先遍历左子树
dfs(node.left);
// 如果 pre 为空,表示当前节点是最左侧节点,更新 head 指针
if (pre == null) {
head = node;
} else { // 否则,更新 pre 右指针和当前节点左指针
node.left = pre;
pre.right = node;
}
// 更新 pre 指针
pre = node;
// 遍历右子树
dfs(node.right);
}