给你二叉搜索树的根节点 root ,该树中的 恰好 两个节点的值被错误地交换。请在不改变其结构的情况下,恢复这棵树 。
- 第一种解决方法,就是使用一个数组进行存放中序遍历的结点,然后找到错误的两个结点交换二者的值。代码如下:
public void recoverTree(TreeNode root) {
List<TreeNode> result = new ArrayList<>();
dfsBST(root,result);
TreeNode wrongNode1 = null;
TreeNode wrongNode2 = null;
for (int i = 1; i < result.size(); i++) {
if (result.get(i).val < result.get(i-1).val){
wrongNode2 = result.get(i);
if (wrongNode1 == null) wrongNode1 = result.get(i-1);
}
}
if (wrongNode1 != null && wrongNode2 !=null){
int exchange = wrongNode1.val;
wrongNode1.val = wrongNode2.val;
wrongNode2.val = exchange;
}
}
private void dfsBST(TreeNode treeNode, List<TreeNode> result){
if(treeNode == null) return;
dfsBST(treeNode.left,result);
result.add(treeNode);
dfsBST(treeNode.right,result);
}
该算法使用了o(n)的时间复杂度,以及O(n)的空间复杂度。
- 第二种解决方法是使用递归隐式或者遍历维持显式栈,来进行元素的存放。代码如下:
private TreeNode pre = null;
private TreeNode wrongNode1 = null;
private TreeNode wrongNode2 = null;
public void recoverTree(TreeNode root) {
dfsBST(root);
if(wrongNode1 != null && wrongNode2 != null){
Integer exchange = wrongNode1.val;
wrongNode1.val = wrongNode2.val;
wrongNode2.val = exchange;
}
}
private void dfsBST(TreeNode treeNode){
if(treeNode == null) return;
dfsBST(treeNode.left);
if (pre != null && pre.val < treeNode.val){
wrongNode2 = treeNode;
if(wrongNode1 == null) wrongNode1 = pre;
}
pre = treeNode;
dfsBST(treeNode.right);
}
该算法的时间复杂度为O(n),空间复杂度为O(h) h为递归或者遍历时BST的树的高度。
- 但是该题目要求需要使用O(1)的空间的算法,那么就需要进行使用莫里斯遍历,该算法比较难,而且实用性不是特别强。就需要简单的了解就行了。