二叉搜索树中的两个节点被错误地交换。
请在不改变其结构的情况下,恢复这棵树。
这道题的关键是找到两个被错误交换的节点。
对于二叉搜索树,一定要把握住各个遍历对应的特征。
二叉搜索树+中序遍历–> 可以得到一个有序数组。那么问题转化为:在一个有序数组中,将两个数交换后,怎样找到这两个数。例如,[1 2 3 4 5 6 7 8] ,如果变成 [1 2 6 4 5 3 7 8],那么这两个数的特点是 6>4,5>3。
方法一:显示中序遍历
因此,最直接的方法是:
1)中序遍历得到有序数组
2)找到被交换节点
3)将树中被交换节点的值交换
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public void recoverTree(TreeNode root) {
List<Integer> nums=new ArrayList<Integer>();
inOrder(root,nums);
int[] swap=findSwap(nums);
recover(root,2,swap[0],swap[1]);
}
private void inOrder(TreeNode root,List<Integer> nums){
if(root==null){
return;
}
inOrder(root.left,nums);
nums.add(root.val);
inOrder(root.right,nums);
}
private int[] findSwap(List<Integer> nums){
int x=-1,y=-1;
for(int i=0;i<nums.size()-1;i++){
if(nums.get(i+1)<nums.get(i)){
y=nums.get(i+1);
if(x==-1){
x=nums.get(i);
}else{
break;
}
}
}
return new int[]{x,y};
}
private void recover(TreeNode root,int count,int a,int b){
if(root==null){
return;
}
if(root.val==a||root.val==b){
root.val= root.val==a?b:a;
count--;
if(count==0) return;
}
recover(root.left,count,a,b);
recover(root.right,count,a,b);
}
}
方法二:隐式中序遍历
可以在中序遍历过程中就找到不同的两个节点,直接交换。
如果要得到中序遍历的结果,应该采用栈的方式迭代遍历。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public void recoverTree(TreeNode root) {
Deque<TreeNode> stack=new ArrayDeque<TreeNode>();
TreeNode x=null,y=null,pred=null;
while(!stack.isEmpty()||root!=null){
while(root!=null){
stack.push(root);
root=root.left;
}
root=stack.pop();
if(pred!=null&&pred.val>root.val){
y=root;
if(x==null){
x=pred;
}else{
break;
}
}
pred=root;
root=root.right;
}
swap(x,y);
}
private void swap(TreeNode a,TreeNode b){
int tmp=a.val;
a.val=b.val;
b.val=tmp;
}
}
方法三:Morris 中序遍历
待填坑。。。