跳至主要內容

Mr.He大约 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;
    }
};