1 题目
2 Java
核心就是利用二叉搜索树的性质,中序序列严格升序
步骤如下:
1 先找到需要交换的两个节点(发生降序)
2 将两个节点值交换
2.1 方法一(中序递归)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int[] exchange = new int[2];
int flag = 0;
int pre = 0;
public void recoverTree(TreeNode root) {
findError(root);
recoverTreeHelper(root);
}
public void findError(TreeNode root){
if(root == null || flag == 3) return;
findError(root.left);
if(flag == 0){
pre = root.val;
flag = 1;
}
else if(pre > root.val){
if(flag == 1){
exchange[0] = pre;
exchange[1] = root.val; // 易错,有可能只有一对降序,这两个交换就可以了
flag = 2;
}
else if(flag == 2){
exchange[1] = root.val;
flag = 3;
}
}
pre = root.val;
findError(root.right);
}
public void recoverTreeHelper(TreeNode root){
if(root == null) return;
recoverTreeHelper(root.left);
if(root.val == exchange[0]) root.val = exchange[1];
else if(root.val == exchange[1]){
root.val = exchange[0];
return;
}
recoverTreeHelper(root.right);
}
}
利用成员变量记录目标值;
仅仅是中序遍历,不需要输出序列,所以递归方法返回值类型可以为void;
目标交换值有以下特点:
下图左输入中序序列 [ 1, 3, 2, 4, null ],输出 [ 1, 2, 3, 4, null ]
3,2一对降序序列,需要交换3和2
右图输入中序序列 [ null, 3, 2, 1, null],输出 [ null, 1, 2, 3, null]
3,2和2,1两对降序序列,需要交换3和1
综上,若一对降序序列,就是这两者;若两对降序序列,第一对前者和第二队后者
=============================================================
其实可以记录需要交换的节点,而非值,这样不需要再次遍历到需要交换的节点,直接交换两节点值
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
TreeNode preRoot, shiftRoot1, shiftRoot2;
public void recoverTree(TreeNode root) {
findError(root);
int val = shiftRoot1.val;
shiftRoot1.val = shiftRoot2.val;
shiftRoot2.val = val;
}
public void findError(TreeNode root){
if(root == null) return;
findError(root.left);
if(preRoot == null) preRoot = root;
else if(preRoot.val > root.val){
if(shiftRoot1 == null){
shiftRoot1 = preRoot;
shiftRoot2 = root; // 易错,有可能只有一对降序,这两个交换就可以了
}
else shiftRoot2 = root;
}
preRoot = root;
findError(root.right);
}
}
=============================================================
findError方法中还可以轻微的化简写法
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
TreeNode preRoot, shiftRoot1, shiftRoot2;
public void recoverTree(TreeNode root) {
findError(root);
int val = shiftRoot1.val;
shiftRoot1.val = shiftRoot2.val;
shiftRoot2.val = val;
}
public void findError(TreeNode root){
if(root == null) return;
findError(root.left);
if(preRoot == null) preRoot = root;
else if(preRoot.val > root.val){
if(shiftRoot1 == null) shiftRoot1 = preRoot;
if(shiftRoot1 != null) shiftRoot2 = root;
}
preRoot = root;
findError(root.right);
}
}