将一个 二叉搜索树 就地转化为一个 已排序的双向循环链表 。
对于双向循环列表,你可以将左右孩子指针作为双向循环链表的前驱和后继指针,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
特别地,我们希望可以 就地 完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中最小元素的指针。
示例 1:
输入:root = [4,2,5,1,3]
输出:[1,2,3,4,5]
解释:下图显示了转化后的二叉搜索树,实线表示后继关系,虚线表示前驱关系。
示例 2:
输入:root = [2,1,3]
输出:[1,2,3]
示例 3:
输入:root = []
输出:[]
解释:输入是空树,所以输出也是空链表。
示例 4:
输入:root = [1]
输出:[1]
提示:
-1000 <= Node.val <= 1000
Node.left.val < Node.val < Node.right.val
Node.val 的所有值都是独一无二的
0 <= Number of Nodes <= 2000
二叉搜索树:二叉树,且根节点比所有左子树的值要大,根节点比所有右子树的值要小
左右子树也准从这个准则
可以整体把树分为三部分:根节点、左子树、右子树
然后将:
根节点,与左子树最大的节点链接起来
根节点,与右子树最小的节点链接起来
递归
就是一个中序遍历
/*
// Definition for a Node.
class Node {
public int val;
public Node left;
public Node right;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val,Node _left,Node _right) {
val = _val;
left = _left;
right = _right;
}
};
*/
class Solution {
Node pre;//指针用于保存中序遍历的前一个节点
Node head;//指针用于记录排序链表的头节点
public Node treeToDoublyList(Node root) {
//边界条件
if(root == null) return null;
inOrder(root);
//组成循环链表
head.left = pre;
pre.right = head;
return head;
}
//中序遍历
public void inOrder(Node root){
//边界条件
if(root == null) return;
//中序遍历左子树
inOrder(root.left);
if(pre != null){
//相对于左子树的最右节点,的右指针,指向root
pre.right = root;
}else{
//找出头结点
head = root;
}
//相当于根节点的左指针,指向左子树的最右节点(加上前面那个,形成双向链表)
root.left = pre;
//当根节点与左子树的关系确定完,则,此时,pre就成了root
pre = root;
System.out.println(root.val);
//中序遍历右子树
inOrder(root.right);
}
}
代码中,只做了 左子树与根节点产生双向链接的操作,而没有做根节点与右子树产生双向链表的操作
这是因为,当中序遍历右子树的时候,执行代码就会将根节点与右子树的最小节点产生链接
如果代码中明确写:根与左子树、根与右子树都产生双向链接,则在中序遍历右子树的时候,就会造成重复