https://leetcode.com/problems/recover-binary-search-tree/
最开始题目说的O(n)解法是中序遍历,把值放到一个数组里,把其中要调整的两个调整好,然后在中序遍历一次把数组里面的值按顺序赋到BST之中。
本题两解。
解法一:
递归中序遍历,保存三个指针:两个是要被交换的节点first、second,一个是当前遍历到结点的前序节点pre。如果当前遍历到的前序节点值大于等于当前节点则该节点存在问题,需要交换。注意如果是发现的第一个有问题的节点,那么需要交换的节点为pre;如果是第二次发现的有问题的节点,那么需要被交换的节点是当前节点cur。
这个解法比较concise,但是问题是其空间复杂度实际上是O(logN)----因为是递归。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
TreeNode firstNode = null;
TreeNode secondNode = null;
TreeNode prevNode = new TreeNode(Integer.MIN_VALUE);
public void recoverTree(TreeNode root) {
if (root == null) {
return;
}
inorder(root);
int temp = firstNode.val;
firstNode.val = secondNode.val;
secondNode.val = temp;
}
private void inorder(TreeNode root) {
if (root == null) {
return;
}
inorder(root.left);
if (prevNode.val >= root.val) {
if (firstNode == null) {
firstNode = prevNode;
}
secondNode = root;
}
prevNode = root;
inorder(root.right);
}
}
解法二:
线索二叉树。
其中序遍历的原理:
如果当前节点cur的左孩子为空,则用pre记录当前节点cur并将cur的右孩子作为当前节点。
如果当前节点cur的左孩子不为空,在当前节点cur的左子树中找到当前节点cur在中序遍历下的前驱节点n1,也就是当前节点cur左子树的最右边的那个节点。
如果前驱节点n1的右孩子为空,则将n1的右孩子设置为当前节点cur,当前节点更新为cur的左孩子。
如果前驱节点n1的右孩子为当前节点cur,则将前驱节点n1的右孩子设为空,用pre记录当前节点cur,当前节点cur更新为其右孩子。
/**
* 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) {
TreeNode pre = null;
TreeNode cur = root;
TreeNode first = null;
TreeNode second = null;
while (cur != null) {
if (pre != null && pre.val >= cur.val) {
if (first == null) {
first = pre;
}
second = cur;
}
if (cur.left != null) {
TreeNode temp = cur.left;
while (temp.right != null && temp.right != cur) {
temp = temp.right;
}
if (temp.right == cur) {
temp.right = null;
pre = cur;
cur = cur.right;
} else {
temp.right = cur;
cur = cur.left;
}
} else {
pre = cur;
cur = cur.right;
}
}
int val = first.val;
first.val = second.val;
second.val = val;
}
}