二叉搜索树中的两个节点被错误地交换。
请在不改变其结构的情况下,恢复这棵树。
给题解二的代码做个笔记。
class Solution { public: void recoverTree(TreeNode* root) { stack<TreeNode*> stk; TreeNode* x = nullptr; TreeNode* y = nullptr; TreeNode* pred = nullptr; while (!stk.empty() || root != nullptr) { while (root != nullptr) { // 这里是中序遍历的访问到左子树最左节点的部分 stk.push(root); root = root->left; } root = stk.top(); // 遍历根节点的部分 stk.pop(); if (pred != nullptr && root->val < pred->val) { // 判断是否存在逆序的部分 y = root; if (x == nullptr) { x = pred; } else break; // 注意这个else,正解是第二个逆序的节点 } pred = root; root = root->right; // 遍历右子树部分 } swap(x->val, y->val); } };
这里的 else break 很精髓。因为调换如果不是发生在相邻两个节点之间,那么就会产生两个逆序。
比如 [1,3,2,4],你发现 3 之后的 2 是逆序,但 4 不是,此时遍历已经完了,那么你就可以确定 3 和 2 需要交换。
那么对于 [7,3,5,1],你发现 7-3 是逆序,还不能直接调换。当你发现第二个逆序 5-1 的时候,才确定是 7 和 1 之间调换。