输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
我的解法
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
import java.util.ArrayList;
public class Solution {
//public static ArrayList<TreeNode> list = new ArrayList<>();
public TreeNode Convert(TreeNode pRootOfTree) {
if(pRootOfTree == null)
return null;
ArrayList<TreeNode> list = new ArrayList<>();
inTraverse(pRootOfTree, list);
//把list中树节点连接成双向链表
TreeNode last = null;
for(int i = 0; i < list.size() - 1; i ++){
list.get(i).left = last;
list.get(i).right = list.get(i + 1);
last = list.get(i);
}
list.get(list.size() - 1).left = last;
list.get(list.size() - 1).right = null;
list.get(0).left = null;
return list.get(0);
}
//中序遍历,把树的节点按顺序加入list中
public void inTraverse(TreeNode pRootOfTree, ArrayList<TreeNode> list){
if(pRootOfTree == null)
return;
if(pRootOfTree.left != null){
inTraverse(pRootOfTree.left, list);
}
list.add(pRootOfTree);
if(pRootOfTree.right != null){
inTraverse(pRootOfTree.right, list);
}
return;
}
}
算法分析:双链表顺序就是中序顺序。把中序遍历结果按顺序存起来,然后拼接成双链表。
答案解法
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
import java.util.ArrayList;
public class Solution {
//开始遍历前,双链表的头部、尾部都为null
TreeNode head = null;
TreeNode tail = null;
//把pRootOfTree转换成双链表,得到了链表头部、尾部,但只返回头部
public TreeNode Convert(TreeNode pRootOfTree) {
if(pRootOfTree == null)
return null;
if(pRootOfTree.left != null){
Convert(pRootOfTree.left);
}
//中序遍历,那么生成头部、尾部的代码肯定在中间部分
//如果链表为null,则head和tail都是pRootOfTree节点
if(tail == null){
head = pRootOfTree;
tail = pRootOfTree;
}else{
//把pRootOfTree加入链表后面,并更新链表尾节点
tail.right = pRootOfTree;
pRootOfTree.left = tail;
tail = pRootOfTree;
}
if(pRootOfTree.right != null){
Convert(pRootOfTree.right);
}
return head;
}
}
算法分析:利用递归,函数的功能就是把树生成双链表。那么把左树生成双链表(只能返回头部),再拼接上root(需要左树的尾部);再把右树生成双链表,再拼接到root后面即可。求左子树尾部是难点,我一开始不知道怎么求,也是因为没想明白它和双向链表的关系。即左子树的头就是双向链表的头,左子树的尾部就是递归到此时双向链表的尾部。那么最开始都为null,则通过递归,头和尾部的初始值最终就会变成最左边的叶子节点,然后设为全局变量。然后return到上一次循环时,链表尾部就是此最左叶节点。接下来只需要进行拼接工作即可。