1、题目
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向
2、解法
1、递归法
import java.util.ArrayList;
public class Solution {
public ArrayList<TreeNode> arr = new ArrayList<>();
public TreeNode Convert(TreeNode pRootOfTree) {
Inorder(pRootOfTree);
// 如果是1个结点或者没有,直接输出
if(arr.size() == 1 || arr.size() == 0)
return pRootOfTree;
TreeNode root = null;
// 使用pre作为中间结点
TreeNode pre = null;
TreeNode node = null;
for(int i=0; i<arr.size()-1 ; i++){
if(i==0){
root = arr.get(i);
root.left = pre;
pre = root;
root.right = arr.get(i+1);
}else{
node = arr.get(i);
node.left = pre;
pre = node;
node.right = arr.get(i+1);
}
}
node = arr.get(arr.size()-1);
node.left = pre;
node.right = null;
return root;
}
//中序遍历
public void Inorder(TreeNode t){
if (t == null) return;
Inorder(t.left);
if(t != null)
arr.add(t);
Inorder(t.right);
}
}
时间复杂度为O(n)
空间复杂度为O(n)
2、使用栈
import java.util.LinkedList;
import java.util.Stack;
public class Solution {
public TreeNode Convert(TreeNode pRootOfTree) {
if (pRootOfTree == null) {
return null;
}
return convert(pRootOfTree);
}
public TreeNode convert(TreeNode root){
Stack<TreeNode> stack = new Stack<>();
LinkedList<TreeNode> queue = new LinkedList<>();
TreeNode node = root;
while(node != null || !stack.isEmpty()){
// 一路走到最左边
while(node != null){
stack.push(node);
node = node.left;
}
// 栈是否为空
if(!stack.isEmpty()){
// 判断的时候,只要看一课树就可以
// 左边结束,根出去,再看右边
node = stack.pop();
queue.offer(node);
node = node.right;
}
}
// 对队列当中的结点修改左右结点
for(int i = 0; i < queue.size(); i++){
// 从右往左执行
TreeNode left = i == 0 ? null : queue.get(i - 1);
TreeNode right = i == queue.size()-1 ? null : queue.get(i+1);
queue.get(i).left = left;
queue.get(i).right = right;
}
return queue.get(0);
}
}
时间复杂度为O(n)
空间复杂度为O(n)
用双向链表的get实际上是很慢的,所以这里采用ArrayList比较好
3、一些概念
3.1 二叉搜索树的前驱和后继
前驱(比它小的结点关键字中的最大值 ) | ||
---|---|---|
结点的左子树 | 结点的左父母 | 结点的右父母的左父母(或往上找左父母) |
后继(比它大的结点关键字中的最小值 ) | ||
---|---|---|
结点的右子树 | 结点的右父母 | 结点的左父母的右父母(或往上找右父母) |