题目描述
给你二叉搜索树的根节点 root ,该树中的 恰好 两个节点的值被错误地交换。请在不改变其结构的情况下,恢复这棵树 。
示例
示例一
输入:root = [1,3,null,null,2]
输出:[3,1,null,null,2]
解释:3 不能是 1 的左孩子,因为 3 > 1 。交换 1 和 3 使二叉搜索树有效。
示例二
输入:root = [3,1,4,null,null,2]
输出:[2,1,4,null,null,3]
解释:2 不能在 3 的右子树中,因为 2 < 3 。交换 2 和 3 使二叉搜索树有效。
解题思路
首先我们要明白BST的特性之一就是其中序遍历的结果是顺序的!那么我们就可以利用中序遍历的思想了。
首先我们需要一个变量prev_node
其指向当前节点的上一个节点,当然其一开始是指向root
节点的。之后我们遍历这个二叉树。如果我们发现当前节点的元素是小于上一个节点的,那么说明我们定位到了错误的节点!用两个指针保存当前节点和前一个节点的地址。
之后,我们遍历完,用刚刚的两个指针把这两个节点的val
值交换就可以。
代码
class Solution {
public:
TreeNode* prev_node = nullptr; //保存前一个节点
TreeNode* pre_node = nullptr; //当找到错误节点时,定位前一个节点的地址
TreeNode* cur_node = nullptr; //当找到错误节点时,定位当前节点的地址
/**
* @brief 遍历节点,定位到错误节点
*
* @param node 当前节点的地址
*/
void traverse(TreeNode* node) {
if (node == nullptr) return;
traverse(node->left);
//找到错误节点
if (prev_node != nullptr && prev_node->val > node->val) {
if (pre_node == nullptr) pre_node = prev_node;
cur_node = node;
}
prev_node = node;
traverse(node->right);
}
/**
* @brief leetcode 提供的函数
*
* @param root 根节点
*/
void recoverTree(TreeNode* root) {
if (root == nullptr) return;
traverse(root);
swap(pre_node->val, cur_node->val);
}
};
参考文献
[1] labuladong的算法小抄[M].付东来