题目描述:
二叉搜索树中的两个节点被错误地交换。
请在不改变其结构的情况下,恢复这棵树。
示例 1:
示例 2:
进阶:
使用 O(n) 空间复杂度的解法很容易实现。
你能想出一个只使用常数空间的解决方案吗?
方法1:
主要思路:
(1)使用中序遍历一个二叉搜索树,应该获得的是一个有序的序列,当交换了两个值之后,会在遍历的过程中,出现两次不符合次序的情形,记录这两次中应该交换的位置即可;
(2)这里使用了迭代的方法中序遍历,保存需要交换的两个结点;
(3)为了能够比较前后两个结点的值,这里需要保存前一个结点的地址;
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void recoverTree(TreeNode* root) {
stack<TreeNode*> st;//使用栈实现中序遍历的迭代方法
//存储两个需要交换的结点的位置
TreeNode* x=nullptr;
TreeNode* y=nullptr;
//存储当前结点的上一个结点
TreeNode* pre=nullptr;
//迭代的中序遍历
while(!st.empty()||root!=nullptr){
while(root){
st.push(root);
root=root->left;
}
root=st.top();
st.pop();
//遍历过程中判断需要交换的位置
if(pre!=nullptr&&pre->val>root->val){
x=root;
if(y==nullptr){//获得第二次的位置后可以直接跳出循环
y=pre;
}
else{
break;
}
}
pre=root;//保存上一个结点的位置
root=root->right;
}
swap(x->val,y->val);//交换两个结点的位置
}
};
方法2:
主要思路:
(1)使用递归实现上述思路;
(2)指针的直接使用成员变量进行操作;
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* x=nullptr;
TreeNode* y=nullptr;
TreeNode* pre=nullptr;
void helper(TreeNode* root,bool& sign){
if(sign||root==nullptr){
return;
}
helper(root->left,sign);
if(pre!=nullptr&&pre->val>root->val){
//cout<<pre->val<<" "<<root->val<<endl;
x=root;
if(y==nullptr){//获得第二次的位置后可以直接跳出循环
y=pre;
}
else{
sign=true;
return;
}
}
pre=root;
helper(root->right,sign);
}
void recoverTree(TreeNode* root) {
bool sign=false;
helper(root,sign);
swap(x->val,y->val);
}
};