题目:
Two elements of a binary search tree (BST) are swapped by mistake.
Recover the tree without changing its structure.
Example 1:
Input: [1,3,null,null,2]
1
/
3
\
2
Output: [3,1,null,null,2]
3
/
1
\
2
Example 2:
Input: [3,1,4,null,null,2]
3
/ \
1 4
/
2
Output: [2,1,4,null,null,3]
2
/ \
1 4
/
3
Follow up:
- A solution using O(n) space is pretty straight forward.
- Could you devise a constant space solution?
题目解析:两个节点的值交换了,变成了非BST,找出两个节点,交换回来,变成BST
解法一:递归inorder
代码如下
/**
* 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* first = NULL;
TreeNode* second = NULL;
TreeNode* pre = NULL;
void findReverse(TreeNode* root)
{
if(root == NULL)
return;
findReverse(root->left);
if(pre != NULL && root->val < pre->val)
{
if(first == NULL)
{
first = pre;
second = root;
}
else
{
second = root;
}
}
pre = root;
findReverse(root->right);
}
void recoverTree(TreeNode* root) {
findReverse(root);
int tmp = first->val;
first->val = second->val;
second->val = tmp;
}
};
解法二:利用栈(inorder)
/**
* 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) {
if(root == NULL)
return;
stack<TreeNode*> stk;
TreeNode* pre = NULL;
TreeNode* first = NULL, *second = NULL;
while(root != NULL || !stk.empty())
{
while(root)
{
stk.push(root);
root = root->left;
}
root = stk.top();
stk.pop();
if(pre != NULL && root->val < pre->val)
{
if(first == NULL)
{
first = pre;
second = root;
}
else{
second = root;
}
}
pre = root;
root = root->right;
}
if(first && second){
int tmp = first->val;
first->val = second->val;
second->val = tmp;
}
}
};
解法三:利用线索树(inorder)
首先线索树的中序遍历算法:
当前遍历的节点为 cur。
1、cur.left 为 null,保存 cur 的值,更新 cur = cur.right
2、cur.left 不为 null,找到 cur.left 这颗子树最右边的节点记做 last
2.1 last.right 为 null,那么将 last.right = cur,更新 cur = cur.left
2.2 last.right 不为 null,说明之前已经访问过,第二次来到这里,表明当前子树遍历完成,保存 cur 的值,更新 cur = cur.right
代码如下:
/**
* 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:
vector<int> InorderTree(TreeNode* root) {
vector<int> res;
TreeNode* cur = root;
while(cur != NULL)
{
if(cur->left == NULL)
{
//val
res.push_back(cur->val;)
cur = cur->right;
}
else
{
/* left-subtree rightest node */
TreeNode* pre = cur->left;
while(pre->right != NULL && pre->right != cur)
{
pre = pre->right;
}
if(pre->right == NULL)
{
pre->right = cur;
cur = cur->left;
}
else
{
//val;
res.push_back(cur->val);
pre->right = NULL;
pre = cur;
cur = cur->right;
}
}
}
}
};
本题解法三节点代码如下:
/**
* 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) {
TreeNode* cur = root;
TreeNode* pre_nw = NULL;
TreeNode* first = NULL,*second = NULL;
while(cur != NULL)
{
if(cur->left == NULL)
{
//val;
if(pre_nw != NULL && cur->val < pre_nw->val)
{
if(first == NULL)
{
first = pre_nw;
second = cur;
}
else
{
second = cur;
}
}
pre_nw = cur;
cur = cur->right;
}
else
{
TreeNode* pre = cur->left;
while(pre->right != NULL && pre->right != cur)
{
pre = pre->right;
}
if(pre->right == NULL)
{
pre->right = cur;
cur = cur->left;
}
else
{
//val
if(pre_nw != NULL && cur->val < pre_nw->val)
{
if(first == NULL)
{
first = pre_nw;
second = cur;
}
else
{
second = cur;
}
}
pre_nw = cur;
pre->right = NULL;
pre = cur;
cur = cur->right;
}
}
}
int tmp = first->val;
first->val = second->val;
second->val = tmp;
}
};