//本文转载于https://www.lularible.cn/blog/37
//作者:lularible
给你二叉搜索树的根节点 root ,该树中的两个节点被错误地交换。请在不改变其结构的情况下,恢复这棵树。
进阶:使用 O(n) 空间复杂度的解法很容易实现。你能想出一个只使用常数空间的解决方案吗?
来源:力扣(LeetCode)
链接:恢复二叉搜索树
class Solution {
public:
void recoverTree(TreeNode* root) {
//定义两个异常结点和前驱结点
TreeNode* first = NULL,*second = NULL,*pre = NULL;
inorderTree(root,first,second,pre);
//交换两个异常结点的值
int tmp = first->val;
first->val = second->val;
second->val = tmp;
}
void inorderTree(TreeNode* root,TreeNode*& first,TreeNode*& second,TreeNode*& pre){
if(!root){
return;
}
//先左
if(root->left){
inorderTree(root->left,first,second,pre);
}
//中间进行处理
if(pre && root->val < pre->val){
if(!first){
first = pre;
second = root;
}
else{
second = root;
}
}
pre = root;
//再右
if(root->right){
inorderTree(root->right,first,second,pre);
}
}
};
当前结点cur无左孩子,继续遍历当前结点cur的右孩子
当前结点cur有左孩子
cur的左子树的最右结点的右结点为空,将cur的最右结点的右孩子指针指向cur,继续遍历cur的左孩子
cur的左子树的最右结点的右结点不为空(即指向cur),则将这个指向置空,继续遍历cur的右孩子
参考链接:https://zhuanlan.zhihu.com/p/101321696
class Solution {
public:
static void morrisPre(TreeNode* root) {
if(!root){
return;
}
TreeNode* cur = root; //当前被访问的结点
TreeNode* mostRight = NULL; //当前被访问结点的左孩子最右结点
while(cur){
mostRight = cur->left;
//情况2:cur有左孩子
if(mostRight){
//条件判断中后一个是为了防止环循环
while(mostRight->right && mostRight->right != cur){
mostRight = mostRight->right;
}
//情况2-1:最右结点右孩子为空
if(!mostRight->right){
mostRight->right = cur;
cout << cur->val << " ";
cur = cur->left;
}
//情况2-2:最右结点右孩子指向cur
else{
mostRight->right = NULL;
cur = cur->right;
}
}
//情况1:cur无左孩子
else{
cout << cur->val << " ";
cur = cur->right;
}
}
}
};
class Solution {
public:
static void morrisIn(TreeNode* root) {
if(!root){
return;
}
TreeNode* cur = root; //当前被访问的结点
TreeNode* mostRight = NULL; //当前被访问结点的左孩子最右结点
while(cur){
mostRight = cur->left;
//情况2:cur有左孩子
if(mostRight){
//条件判断中后一个是为了防止环循环
while(mostRight->right && mostRight->right != cur){
mostRight = mostRight->right;
}
//情况2-1:最右结点右孩子为空
if(!mostRight->right){
mostRight->right = cur;
cur = cur->left;
}
//情况2-2:最右结点右孩子指向cur
else{
mostRight->right = NULL;
cout << cur->val << " ";
cur = cur->right;
}
}
//情况1:cur无左孩子
else{
cout << cur->val << " ";
cur = cur->right;
}
}
}
};
class Solution { public: static void morrisPos(TreeNode* root) { if(!root){ return; } TreeNode* cur = root; //当前被访问的结点 TreeNode* mostRight = NULL; //当前被访问结点的左孩子最右结点 while(cur){ mostRight = cur->left; //情况2:cur有左孩子 if(mostRight){ //条件判断中后一个是为了防止环循环 while(mostRight->right && mostRight->right != cur){ mostRight = mostRight->right; } //情况2-1:最右结点右孩子为空 if(!mostRight->right){ mostRight->right = cur; cur = cur->left; } //情况2-2:最右结点右孩子指向cur else{ mostRight->right = NULL; print(cur->left); cur = cur->right; } } //情况1:cur无左孩子 else{ cur = cur->right; } } print(root); } //反序打印root、root->right、root->right->right...... static void print(TreeNode* root){ TreeNode* tail = reverseEdge(root); TreeNode* cur = tail; while(cur){ cout << cur->val << " "; cur = cur->right; } reverseEdge(tail); } //将root、root->right、root->right->right......指针反向 static void TreeNode* reverseEdge(TreeNode* root){ TreeNode* pre = NULL; TreeNode* next = NULL; while(root){ next = root->right; root->right = pre; pre = root; root = next; } return pre; } };
//本文转载于https://www.lularible.cn/blog/37
//作者:lularible