题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表,如下图所示:
要求:空间复杂度为O(1),即不能创建任何新的结点,只能调整树中结点的指向,时间复杂度为O(n)。
示例
输入:{10,6,14,4,8,12,16}(二叉树的根结点)
输出:双向链表的头结点。
二叉搜索树
二叉搜索树,也称二叉排序树,具有以下性质:
- 若左子树不为空,则左子树上的所有结点的值均小于根结点的值;
- 若右子树不为空,则右子树上所有结点的值均大于根结点的值;
- 左右子树也分别为二叉排序树。
由于二叉搜索树具有以上性质,可以快速查找、插入和删除。
解题思路
可以发现,二叉树的中序遍历刚好是排序好的序列,因此我们可以中序遍历二叉树,将遍历结果存储到数组当中,再对数组遍历,改变结点的左右结点,最后生成双向链表,但是其空间复杂度为O(n)。
既然利用数组不满足时间复杂度要求,我们可以通过创建两个指针结点,在遍历的同时调整结点之间的指针,具体做法如下:
- 创建pre结点与head结点;
- 若二叉树为空,则返回空;
- 否则递归遍历左子树;
- 遍历当前结点,并修改当前结点的left以及pre结点的right;
- 更新pre结点为当前结点;
- 若head结点为空,则将head结点指向当前结点;
- 递归遍历当前结点的右子树;
- 返回双向链表的头结点。
代码实现
//Java代码
public class Solution {
TreeNode pre = null;
TreeNode head = null;
public void inOrder(TreeNode node){
if(node == null) return;
inOrder(node.left);
if(pre != null){
this.pre.right = node;
node.left = this.pre;
}
this.pre = node;
if(head == null) this.head = node;
inOrder(node.right);
}
public TreeNode Convert(TreeNode pRootOfTree) {
inOrder(pRootOfTree);
return this.head;
}
}
# Python代码
class Solution:
def Convert(self , pRootOfTree ):
def inOrder(node):
if node == None:
return
inOrder(node.left)
if self.pre != None:
self.pre.right = node
node.left = self.pre
if self.head == None:
self.head = node
self.pre = node
inOrder(node.right)
self.pre = None
self.head = None
inOrder(pRootOfTree)
return self.head