原题链接:https://leetcode-cn.com/problems/recover-binary-search-tree/
最初的想法:找到两个交换的数据,然后换一下。找数据的时候用到中序遍历,交换的时候需要寻找到节点再替换。代码出现了很多的错误,基本都集中在找交换数据的时候,有时候找不全有时候又多找,很难找到适应各种情况的被交换数据。
改进:惯性思维是bst中序遍历会将值升序,可是我只在动态数组中放入了值,最后交换的时候还是需要找,不如直接把节点放进动态数组,不是找值,而是直接找节点。
寻找被交换的值有一种很巧妙的做法
思考分为这两种情况,一种是数据相邻,一种是不相邻。
不相邻 1 2 3 4 5 ==> 1 4 3 2 5 如果i>i+1 i被交换 j>j+1 j+1被交换
相邻 1 2 3 4 ==> 1 3 2 4 如果i>i+1 i被交换 i<i-1 i也被交换
以上两种情况一种出现了一次大于,一种出现了两次,并且第一次出现时前一个是被交换数据,第二个出现时后一个才是。
此外还有一种非常特殊的情况1 2 3 4 5==>1 4 3 2 5如果没有 25就是43交换,有了就是24交换。所以3就是一个中间态,后面出现大于还是要替换它。因为前面不可能知道后面出现不出现,所以我们只能先赋值。若出现了别的那再改。
为此想到第一个大于的值一定要存,第二个被大于的值一定要存,但是第二个不一定出现,所以用xy存,y用作中间存储,x存第一个。
package 二叉搜索树;
import java.util.ArrayList;
/**
https://leetcode-cn.com/problems/recover-binary-search-tree/
* @author zxdn
*
*/
public class _99_恢复二叉搜索树 {
ArrayList<TreeNode> array = new ArrayList();
public void postOrder(TreeNode node) {
if(node == null) return;
postOrder(node.left);
array.add(node);
postOrder(node.right);
}
public void recoverTree(TreeNode root) {
postOrder(root);
TreeNode x = null;
TreeNode y = null;
//这个循环简单但是难想
//x存前面那个值,y存后面那个值,如果后面不出现大于的情况,那就是符合相邻的情况
//若后面出现了大于的情况,那y正好指向的是第二个。
for (int i = 0; i < array.size() - 1; i++) {
if(array.get(i).val > array.get(i + 1).val) {
y = array.get(i+1);
if(x == null) {
x= array.get(i);
}
}
}
//交换这两个节点的值
if(x != null && y != null) {
int tmp = x.val;
x.val = y.val;
y.val = tmp;
}
}
}