Solution 1
实际上就是 98. Validate Binary Search Tree 的变体,上一题要求我们验证树的有效性,这里就是要进一步恢复,也就是要将不满足绝对递增的中序遍历序列恢复成绝对递增序列。本题限定出问题的只有一对数字,因此问题的中序遍历序列会有最多两个地方(如果调换位置相邻,出问题的只有一个地方)出现非绝对递增的情形,找到后,将前一个的左侧和后一个的右侧进行调换。
在使用Morris遍历法进行调整的时候,由于我之前写的方案是在调整右子树的时候直接解除循环,因此会影响树的结构,借鉴了另外一种Morris遍历法的实现。
- 时间复杂度: O ( n ) O(n) O(n),其中 n n n为树中的节点个数,线性遍历
- 空间复杂度: O ( 1 ) O(1) O(1),Morris遍历法,仅维护常数个状态量
/**
* 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 = nullptr;
TreeNode* check = nullptr;
TreeNode* bigger = nullptr;
TreeNode* smaller = nullptr;
while (cur != nullptr) {
if (cur->left == nullptr) {
if (check != nullptr && check->val > cur->val) {
smaller = cur;
if (bigger == nullptr) {
bigger = check;
}
}
check = cur;
cur = cur->right;
}
else {
// 调整树结构
pre = cur->left;
while (pre->right != nullptr && pre->right != cur) { pre = pre->right; }
if (pre->right == nullptr) {
pre->right = cur;
cur = cur->left;
} else {
// 根节点位置,说明左子树已经访问完了(一个循环出现了)
if (check != nullptr && check->val > cur->val) {
smaller = cur;
if (bigger == nullptr) {
bigger = check;
}
}
check = cur;
pre->right = nullptr; // 解除循环
cur = cur->right;
}
}
}
swap(bigger->val, smaller->val);
}
};
Solution 2
Solution 1的Python实现
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def recoverTree(self, root: Optional[TreeNode]) -> None:
"""
Do not return anything, modify root in-place instead.
"""
cur = root
pre = None
check = None
bigger = None
smaller = None
while cur is not None:
if cur.left is None:
if check is not None and check.val > cur.val:
smaller = cur
if bigger is None:
bigger = check
check = cur
cur = cur.right
else:
pre = cur.left
while pre.right is not None and pre.right != cur: pre = pre.right
if pre.right is None:
pre.right = cur
cur = cur.left
else:
if check is not None and check.val > cur.val:
smaller = cur
if bigger is None:
bigger = check
check = cur
pre.right = None
cur = cur.right
bigger.val, smaller.val = smaller.val, bigger.val