题目的链接在这里:https://leetcode-cn.com/problems/recover-binary-search-tree/
题目大意
给你二叉搜索树的根节点 root ,该树中的两个节点被错误地交换。请在不改变其结构的情况下,恢复这棵树。进阶:使用 O(n) 空间复杂度的解法很容易实现。你能想出一个只使用常数空间的解决方案吗?
一、示意图
二、解题思路
中序遍历
暴力版
代码如下:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int count=400;
public void recoverTree(TreeNode root) {
List<TreeNode> list=new ArrayList<>();
//先进行中序遍历
//就必须是 这个节点和他前一个节点的比较就行了
if(root==null){
return;
}
//使用栈进行中序遍历
Stack<TreeNode> stack=new Stack<>();
TreeNode temp=root;
while (temp!=null||!stack.isEmpty()){
//一直递归到他最左边的值
while (temp!=null){
/**
* 一直找到最左边的
*/
stack.push(temp);
//那就这里不判断
/* if(temp.left!=null){
if(temp.left.val>temp.val){
//直接不合规
swap(temp.left,temp);
//说明不能return
return;
}else{
temp=temp.left;
}
}else {
temp = temp.left;
}*/
temp = temp.left;
}
//直接设置一个数组来存这些好了
//现在temp就是指向null 而栈顶元素就是当前最左边的了
if(!stack.isEmpty()){
//这里就进行一次和上一个的查找
//这里要进行一次查重
temp=stack.pop();
// System.out.println("temp.val = " + temp.val);
if(list.size()!=0){
//说明他存在上一个 问题只可能出现在这
TreeNode l=list.get(list.size()-1);
//System.out.println(".va = " +l.val);
//让l和这个temp进行对比
if(temp.val<l.val){
//说明违规 就需要换位置
swap(temp,l);
//说明这边是不能return的 他们两个换号之后 list最
list.add(temp);
//然后指向
}
else{
//那就正常进行
list.add(temp);
}
}
//这个temp就在最左边的这个
else {
list.add(temp);
}
//这里的问题吧 需要让3和右边最左边的数相比较 和他前一个节点的比较
//temp这个时候是一个树的最左子树 他的前一个 那就和他后一个进行比较也行吧
/* if(temp.right!=null){
TreeNode te=temp.right;
//先和最右边的最左边进行比较
while (te.left!=null){
te=te.left;
}
//te就是指向右子树的最左边
if(te.val<temp.val){
//说明违规了
swap(te,temp);
return;
}
//说明这个点还存在右子树
//先进行判断
if(temp.right.val<temp.val){
//说明违规 直接进行交换
swap(temp.right,temp);
return;
}else{*/
/* //那就正常
temp=temp.right;
}
}
else{
//也是正常
temp=temp.right;
}*/
temp=temp.right;
//System.out.println("temp.right.val = " + temp.right.val);
}
//要么就是在需要来一遍
}
count--;
if(count!=0){
recoverTree(root);
}
}
private void swap(TreeNode right, TreeNode temp) {
//交换的代码 交换的是值
int t=right.val;
right.val=temp.val;
temp.val=t;
}
}
优化版
代码如下:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
/**
* 可能会出现要交换好几次 所以记录 第一个下降前和第二个下降后的元素兑换
* @param root
*/
public void recoverTree(TreeNode root) {
TreeNode pre = null;
TreeNode ord= null;
TreeNode te=null;
boolean flag=true;
List<TreeNode> list=new ArrayList<>();
//先进行中序遍历
//就必须是 这个节点和他前一个节点的比较就行了
if(root==null){
return;
}
//使用栈进行中序遍历
Stack<TreeNode> stack=new Stack<>();
TreeNode temp=root;
while (temp!=null||!stack.isEmpty()){
//一直递归到他最左边的值
while (temp!=null){
/**
* 一直找到最左边的
*/
stack.push(temp);
temp = temp.left;
}
if(!stack.isEmpty()){
//这里就进行一次和上一个的查找
//这里要进行一次查重
temp=stack.pop();
// System.out.println("temp.val = " + temp.val);
if(list.size()!=0){
//说明他存在上一个 问题只可能出现在这
TreeNode l=list.get(list.size()-1);
// System.out.println(".va = " +l.val);
//让l和这个temp进行对比
if(temp.val<l.val){
//这里不交换 而是做标记
if(flag){
//万一只进行一次交换
//说明是第一次交换 那就记录第一次交换中的前一个数组也就是这个3
pre=l;
te=temp;
flag=false;
}else{
//说明不是第一次交换 那就把第二次交换的后一个也进行标记
ord=temp;
}
}
else{
//那就正常进行
list.add(temp);
}
}
//这个temp就在最左边的这个
else {
list.add(temp);
}
temp=temp.right;
//System.out.println("temp.right.val = " + temp.right.val);
}
//要么就是在需要来一遍
}
//直到这里再交换 就需要把两次交换还是一次交换的统计出来
if(ord!=null) {
swap(pre, ord);
}else{
swap(pre,te);
}
}
private void swap(TreeNode right, TreeNode temp) {
//交换的代码 交换的是值
int t=right.val;
right.val=temp.val;
temp.val=t;
}
}