大约 1 分钟
解决这个问题的关键在于利用 BST 的性质:BST 的中序遍历结果是一个严格递增的序列。
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {void} Do not return anything, modify root in-place instead.
*/
var recoverTree = function(root) {
// 用于记录前一个访问的节点
let prev = null;
// 记录第一个需要交换的节点
let first = null;
// 记录第二个需要交换的节点
let second = null;
// 中序遍历函数
function inorder(node) {
if (!node) return;
// 遍历左子树
inorder(node.left);
// 处理当前节点
// 如果前一个节点的值大于当前节点的值,说明出现了逆序
if (prev && prev.val > node.val) {
// 如果 first 还没找到,这就是第一个错误节点(较大的那个)
if (!first) {
first = prev;
}
// 无论是否是第一次发现逆序,当前的 node(较小的那个)都可能是第二个错误节点
// 如果是相邻交换,这里会更新一次;如果不相邻交换,这里会更新两次,最终停留在最后那个小的节点上
second = node;
}
// 更新 prev 为当前节点
prev = node;
// 遍历右子树
inorder(node.right);
}
// 执行中序遍历
inorder(root);
// 如果找到了两个错误节点,交换它们的值
if (first && second) {
const temp = first.val;
first.val = second.val;
second.val = temp;
}
};