首页 > 试题广场 >

恢复二叉搜索树

[编程题]恢复二叉搜索树
  • 热度指数:14252 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
二叉搜索树(BST)中的两个节点的值被错误地交换了,
请在不改变树的结构的情况下恢复这棵树。
备注;
用O(n)的空间解决这个问题的方法太暴力了,你能设计一个常数级空间复杂度的算法么?

示例 1:

输入: [1,3,null,null,2]
    1
  /
3
 \
  2

输出: [3,1,null,null,2]
    3
  /
1
 \
  2



说明:本题目包含复杂数据结构TreeNode,点此查看相关信息
/*
Morris中序遍历二叉树,空间复杂度O(1),耗时比较高。。没过测试,试了几个线下应该可以,
时间复杂度O(n),但是有些时间节点会遍历两次。
*/  import java.util.*;
public class Solution {
    public void recoverTree(TreeNode root) {
        TreeNode cur = root;
        TreeNode mostRight;
        TreeNode firstStrange=null;
        TreeNode firstStrange_next = new TreeNode(Integer.MIN_VALUE);
        TreeNode pre=new TreeNode(Integer.MIN_VALUE);
        while (cur!=null) {
            if (cur.left!=null) {
                mostRight = cur.left;
                while(mostRight.right!=null&&mostRight.right!=cur) {
                    mostRight=mostRight.right;
                }
                if (mostRight.right==null) {
                    mostRight.right=cur;
                    cur = cur.left;
                    continue;
                }
                else {
                    mostRight.right = null;
                }
            }
            if (pre.val>cur.val) {
                if (firstStrange==null) {
                    firstStrange=pre;
                    firstStrange_next=cur;
                }
                else {
                    int term = firstStrange.val;
                    firstStrange.val = cur.val;
                    cur.val = term;
                    return;
                }
            }
            pre = cur;
            cur =cur.right;
        }
        int term = firstStrange.val;
        firstStrange.val = firstStrange_next.val;
        firstStrange_next.val = term;
        return;
    }
}

发表于 2019-07-27 12:25:23 回复(0)
 /**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    TreeNode pre,p,q;
    public void recoverTree(TreeNode root) {
        pre=p=q=null;
        dfs(root);
        int temp=p.val;
        p.val=q.val;
        q.val=temp;
    }
    public void dfs(TreeNode root){
        if(root == null)
            return;
        dfs(root.left);
        if(pre != null && pre.val > root.val){
            if(p == null){
                p=pre;
                q=root;
            }else{
                q=root;
            }
        }
        pre=root;
        dfs(root.right);
    }
}

发表于 2018-02-27 10:22:27 回复(0)

//只要用到递归空间复杂度至少是O(书的高度),所以要做到O(1)的空间复杂度,只有Morris中序遍历

public void recoverTree(TreeNode root) { if(root==null) return; TreeNode cur=root,m1=null,m2=null,last=null; while(cur!=null) { TreeNode pre=cur.left; if(pre!=null) { while(pre.right!=null&&pre.right!=cur) pre=pre.right; if(pre.right==null) { pre.right=cur; cur=cur.left; continue; } else pre.right=null; } if(last==null) last=cur; else { if(m1==null&&last.val>cur.val) { m1=last; m2=cur; } else if(m1!=null&&last.val>cur.val) m2=cur; last=cur; } cur=cur.right; }  int t=m1.val; m1.val=m2.val; m2.val=t; } 
编辑于 2017-11-26 20:49:10 回复(1)
//满足空间复杂度为常数
//思路:设定两个指针用来指向两处错误处和一个pre指针指向中序遍历的前一个结点。
public class Solution {
    TreeNode pre,mistake1,mistake2;
    public void recoverTree(TreeNode root) {
        inTraversal(root);
        mistake1.val=mistake2.val^mistake1.val^(mistake2.val=mistake1.val);
    }
    public void inTraversal(TreeNode root){
        if(root==null) return ;
        inTraversal(root.left);
        if(pre!=null&&pre.val>root.val){
            if(mistake1==null){
                mistake1=pre;
                mistake2=root;
            }else mistake2=root;
        }
        pre=root;
        inTraversal(root.right);
    }
}

发表于 2017-05-02 21:46:42 回复(5)
import java.util.*;
public class Solution {
    public void recoverTree(TreeNode root) {
		List<TreeNode> list = new ArrayList<>();
		inorder(root, list);
		TreeNode first = null, second = null;
		for (int i = 0; i < list.size() - 1; i ++) {
			if(list.get(i).val > list.get(i + 1).val) {
				first = list.get(i);
				break;
			}
		}
		for (int i = list.size() - 1; i > 0; i --) {
			if(list.get(i).val < list.get(i - 1).val) {
				second = list.get(i);
				break;
			}
		}
		first.val = second.val ^ first.val ^ (second.val = first.val);
	}
	public static void inorder(TreeNode root, List<TreeNode> list) {
		if(root != null) {
			inorder(root.left, list);
			list.add(root);
			inorder(root.right, list);
		}
	}
}

发表于 2017-04-15 15:19:18 回复(1)
public void recoverTree(TreeNode root) {
        TreeNode pre = null;
        TreeNode first = null, second = null;
        // Morris Traversal
        TreeNode temp = null;
		while(root!=null){ if(root.left!=null){
				// connect threading for root temp = root.left;
				while(temp.right!=null && temp.right != root) temp = temp.right;
				// the threading already exists if(temp.right!=null){ if(pre!=null && pre.val > root.val){ if(first==null){first = pre;second = root;} else{second = root;}
				    } pre = root;
				    
					temp.right = null; root = root.right;
				}else{
					// construct the threading
					temp.right = root; root = root.left;
				}
			}else{ if(pre!=null && pre.val > root.val){ if(first==null){first = pre;second = root;} else{second = root;}
				} pre = root; root = root.right;
			}
		}
		// swap two node values; if(first!= null && second != null){
		    int t = first.val;
		    first.val = second.val;
		    second.val = t;
		}
    }

发表于 2017-03-12 11:10:10 回复(0)
public class Solution {
    
    TreeNode firstElement = 
    
    TreeNode firstElement = null;
    TreeNode secondElement = 
    TreeNode secondElement = null;
    
    // The reason for this initialization is to avoid null pointer exception in the first comparison when prevElement has not been initialized
    TreeNode prevElement = new TreeNode(Integer.MIN_VALUE);
    
    
    
    public void recoverTree(TreeNode root) {
        
        
        
        // In order traversal to find the two elements
        traverse(root);
        
        // Swap the values of the two nodes
        int temp = firstElement.val;
        firstElement.
        firstElement.val = secondElement.val;
        secondElement.
        secondElement.val = temp;
    }
    
    
    }
    
    private void traverse(TreeNode root) {
        
        
        
        if (root == null)
            
            return;
            
        traverse(root.left);
        
        
            
        traverse(root.left);
        
        // Start of "do some business", 
        // If first element has not been found, assign it to prevElement (refer to 6 in the example above)
        if (firstElement == null && prevElement.val >= root.val) {
            firstElement = prevElement;
        }
    
        
            firstElement = prevElement;
        }
    
        // If first element is found, assign the second element to the root (refer to 2 in the example above)
        if (firstElement != null && prevElement.val >= root.val) {
            secondElement = root;
        }        
        prevElement = root;

        
            secondElement = root;
        }        
        prevElement = root;
        // End of "do some business"
        traverse(root.right);
}

发表于 2017-03-12 11:09:23 回复(0)