问题:
Two elements of a binary search tree (BST) are swapped by mistake.
Recover the tree without changing its structure.
Note:
A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?
这个问题场景是:
二叉搜索树中,节点的值存在问题,在不改变树结构的前提下,修复该二叉搜索树。
代码示例:
1、O(n) space的解法
这种解法比较简单,主要的依据是:
正常的二叉搜素树,按照中序遍历后,
节点的值应该是按照从小到大的顺序排列的。
按照这种思路,可以得到如下的解法:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public void recoverTree(TreeNode root) {
List<TreeNode> nodeList = new ArrayList<>();
//先中序遍历
inOrder(root, nodeList);
//得到当前的节点值
int[] values = new int[nodeList.size()];
for (int i = 0; i < nodeList.size(); ++i) {
values[i] = nodeList.get(i).val;
}
//重新排序
Arrays.sort(values);
//将排序后的值赋给节点
for (int i = 0; i < nodeList.size(); ++i) {
nodeList.get(i).val = values[i];
}
}
//中序排序主要就用到了递归
//先左子树;然后中间节点;再右子树即可
private void inOrder(TreeNode root, List<TreeNode> rst) {
if (root == null) {
return;
}
inOrder(root.left, rst);
rst.add(root);
inOrder(root.right, rst);
}
}
2、上述方法的改进
实际上在中序遍历时,我们并不需要记录所有节点的信息,
仅保留出现问题的节点即可。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
//prev记录遍历的前一个节点
//first记录出现问题的第一个节点
//second记录出现问题的第二个节点
TreeNode prev, first, second;
public void recoverTree(TreeNode root) {
//依然中序遍历节点
inOrder(root);
//如果找到出现问题的两个节点,则交换这两个节点的值
if (first != null && second != null) {
int tmp = first.val;
first.val = second.val;
second.val = tmp;
}
}
private void inOrder(TreeNode root) {
if (root == null) {
return;
}
inOrder(root.left);
if (prev != null) {
//前一个节点的值大于当前节点
//说明出现问题
if (prev.val > root.val) {
//如果第一次遇到这种情况,那么第一个出错的节点就是当前的prev
if (first == null) {
first = prev;
}
//第一次时,第二个节点记录为root
//即假设出错的两个节点“紧挨着”
//若第二次重新进入该分支
//则出错的两个节点有“距离”,此时第二出错节点为当前的root
second = root;
}
}
//prev永远记录前一个节点
prev = root;
inOrder(root.right);
}
}