题目:
给你二叉搜索树的根节点 root ,该树中的 恰好 两个节点的值被错误地交换。请在不改变其结构的情况下,恢复这棵树 。
示例 1:
输入:root = [1,3,null,null,2]
输出:[3,1,null,null,2]
解释:3 不能是 1 的左孩子,因为 3 > 1 。交换 1 和 3 使二叉搜索树有效。
解答:
首先这是有关于二叉搜索树的问题。总结一下当时没做出来的原因是对二叉搜索树中序遍历出来的结果还是不太熟悉,还有就是对于错误节点处理上存在问题。
正确思路:
二叉搜索树中序遍历出来的结果一定是一个递增的序列。如果其中两个节点的值被互换了,那么必然会出现两种情况
1. 两个错误的值相连
2.两个错误的值中间夹杂着正确的序列
此时一个问题就是我们在遍历完成之后应该如何记录这两个错误的值。
一个思路就是定义两个变量(errorOne,errorTwo)来对应两个错误的节点(一定是节点,而不是节点的数值!),其次我们需要比较本节点和上一个节点,那么就需要一个变量(pre)来保存上一个节点。如果利用递归方法来实现中序遍历,那么在处理节点的时候,我们应该:
1.首先看errorOne是不是空,如果是空而且本节点要比pre小,那么说明有问题,此时我们把pre赋值给errorOne
2.然后如果errorOne不是空,说明前面已经找出了一个错误,如果本节点还比pre小,那么我们就把本节点赋值给errorTwo
3.不要忘了将本节点赋值给pre,进入下层递归
最后递归完成,互换两个错误节点的值即可。
具体代码:
public class Solution99 {
TreeNode errorOne = null;
TreeNode errorTwo = null;
TreeNode pre = new TreeNode(Integer.MIN_VALUE);
public void recoverTree(TreeNode root) {
TreeNode pre = null;
DFS(root);
int temp = errorOne.val;
errorOne.val=errorTwo.val;
errorTwo.val=temp;
}
private void DFS(TreeNode root) {
if(root==null) return;
DFS(root.left);
if(Objects.isNull(errorOne) && root.val<pre.val){
errorOne=pre;
}
if(!Objects.isNull(errorOne) && root.val<pre.val){
errorTwo=root;
}
pre=root;
DFS(root.right);
}
static 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;
}
}
}