题目描述:
- 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
- 牛客链接
问题分析:
- 一般涉及到二叉树的问题,大部分都有个大套路,便是递归处理左右子树,以此缩小问题规模,此题也一样。
- 因为是二叉搜索树,所以其中序遍历的结果应该是从小到大排序的。
- 解法主要有两个大方向,一是用额外容器(方法一),二是不用额外容器(方法2),只是指针调整
- 方法一:用额外容器收集该二叉树中序遍历的结果,然后依次遍历该容器中的每个节点,改变left与right指针,left指向该节点的前一个节点,right指向该节点的后一个节点,然后将每个节点串成一个双向链表。
- 方法二:先递归遍历左子树,形成一个双向链表lList,假设process()函数实现该功能;再递归遍历右子树,形成一个双向链表rList,然后与当前节点相连。这是一个大思路,但是lList与当前节点相连时,必须知道该链表的尾节点。那么如何记录尾节点呢?
- 2.1 :process()函数返回双向链表的头结点,当lList每一次与当前节点相连时,必须遍历该链表,找到该链的尾节点,然后才能连接。
这种方法每一次都要遍历,比较费时。 - 2.2: process()函数返回一个Node[]数组,Node[0]存着该链表头节点,Node[1]存放该链表尾节点,这样便于连接。
- 2.3: process()函数返回双向链表的尾节点,但是该节点的right指针指向该双向链表的头结点,比Node[]数组方法节省空间,有点线索二叉树的意思。但最终还需要把指针改回来,改成null。
经验教训
- 二叉树用递归解题的经典大套路
- 二叉树可能会出现左子树或者右子树不存在的情况,一定要注意这样边界条件。具体细节见代码。
代码实现
public static TreeNode convert1(TreeNode head) {
if (head == null) {
return null;
}
Queue<TreeNode> queue = new LinkedList<>();
inOrderToQueue(head, queue);
TreeNode start = queue.poll();
start.left = null;
start.right = null;
TreeNode preNode = start;
while (! queue.isEmpty()) {
TreeNode curNode = queue.poll();
preNode.right = curNode;
curNode.left = preNode;
curNode.right = null;
preNode = curNode;
}
return start;
}
public static void inOrderToQueue(TreeNode head, Queue<TreeNode> queue) {
if (head == null) {
return;
}
inOrderToQueue(head.left, queue);
queue.add(head);
inOrderToQueue(head.right, queue);
}
public static TreeNode convert2(TreeNode head) {
if (head == null ) {
return null;
}
TreeNode[] res = process(head);
return res[0];
}
public static TreeNode[] process(TreeNode head) {
if (head == null) {
return new TreeNode[] {null , null};
}
TreeNode[] left = process(head.left);
TreeNode[] right = process(head.right);
TreeNode start = head;
TreeNode end = head;
head.left = left[1];
if (left[1] != null) {
left[1].right = head;
start = left[0];
}
head.right = right[0];
if (right[0] != null) {
right[0].left = head;
end = right[1];
}
return new TreeNode[] {start, end};
}
public static TreeNode convert2(TreeNode head) {
if (head == null) {
return null;
}
TreeNode tail = process(head);
TreeNode start = tail.right;
tail.right = null;
return start;
}
public static TreeNode process(TreeNode head) {
if (head == null) {
return null;
}
TreeNode lTail = process(head.left);
TreeNode rTail = process(head.right);
head.left = null;
head.right = head;
TreeNode headAll = head;
TreeNode tailAll = head;
if (lTail != null) {
TreeNode lHead = lTail.right;
head.left = lTail;
lTail.right = head;
head.right = lHead;
headAll = lHead;
}
if (rTail != null) {
TreeNode rHead = rTail.right;
head.right = rHead;
rHead.left = head;
rTail.right = headAll;
tailAll = rTail;
}
return tailAll;
}