题目:
Two elements of a binary search tree (BST) are swapped by mistake.
Recover the tree without changing its structure.
Note:
A solution using O(n ) space is pretty straight forward. Could you devise a constant space solution?
题目很简单,就是一个二叉搜索树,其中有两个节点被调换了,需要恢复过来。
可以直接修改节点的value,而不需要移动节点。
如果对二叉搜索树的结构和遍历过程不熟悉,会觉得有点不好下手。
其实稍微理一下还是比较简单的,思路过程如下:
- 二叉搜索树,中序遍历取节点value时,得到的是一个有序(升序)的数组;
- 交换了两个节点,实际上在中序遍历取value得到数组中,数组会出现两个异常的值(与相邻值对比不满足升序);
- 这两个异常值所对应的节点也就是被调换的节点;
- 把这两个节点的值进行替换则可恢复成原来的二叉搜索树。
例如某个二叉搜索树中序遍历取value后得到的数组是:
1,2,3,4,5,6,7,8,9
现在交换3和7所在的节点,再次中序遍历取value后得到的数组是:
1,2,7,4,5,6,3,8,9
通过中序遍历很容易得到此二叉搜索树的异常节点为7和3(分别对比7/4和6/3的时候);
然后进行最后一步替换这两个节点的值就可以。
感觉把一个很简单的问题说复杂了,直接看一下代码:
public class Solution {
private TreeNode preNode, firstMisNode, secondMisNode;
public void recoverTree(TreeNode root)
{
preNode = firstMisNode = secondMisNode = null;
dfs(root);
int tmp = firstMisNode.val;
firstMisNode.val = secondMisNode.val;
secondMisNode.val = tmp;
}
private void dfs(TreeNode root)
{
if (root == null)
{
return;
}
dfs(root.left);
if (preNode != null && preNode.val > root.val)
{
if (firstMisNode == null)
firstMisNode = preNode;
secondMisNode = root;
}
preNode = root; //这里可以看成是中序遍历当前节点的过程,只不过顺便标记一下成前一个节点preNode(相对下一个节点而言)
dfs(root.right);
}
}
再做一下扩展,判断一棵树是不是二叉搜索树。
和上面的思路大致是相同的,有两种实现的代码,都很直观简单,但代码简洁性,时间复杂度和空间复杂度第二种都要优于第一种。
代码实现一:
public class Solution
{
public boolean isValidBST(TreeNode root)
{
pre=null;
if(root==null)
return true;
ArrayList<Integer> aList=new ArrayList<Integer>();
visitBST(root,aList);
boolean res=true;
for(int i=1;i<aList.size();i++){
if(aList.get(i)<aList.get(i-1)){
res=false;
break;
}
}
return res;
}
private void visitBST(TreeNode root,ArrayList<Integer> aList){
if(root==null)
return;
visitBST(root.left,aList);
aList.add(root.val);
visitBST(root.right,aList);
}
}
代码实现二,算是比较直观简洁了:
public class Solution {
TreeNode pre=null;
public boolean isValidBST(TreeNode root) {
if(root==null)
return true;
if(!isValidBST(root.left))
return false;
if(pre!=null&&pre.val>=root.val)
return false;
pre=root;
return isValidBST(root.right);
}
}