「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战」。
题目
给你二叉搜索树的根节点 root ,该树中的两个节点的值被错误地交换。请在不改变其结构的情况下,恢复这棵树。
示例 1:
输入:root = [1,3,null,null,2] 输出:[3,1,null,null,2] 解释:3 不能是 1 左孩子,因为 3 > 1 。交换 1 和 3 使二叉搜索树有效。
示例 2:
输入:root = [3,1,4,null,null,2] 输出:[2,1,4,null,null,3]
解释:2 不能在 3 的右子树中,因为 2 < 3 。交换 2 和 3 使二叉搜索树有效。
提示:
树上节点的数目在范围 [2, 1000] 内 -231 <= Node.val <= 231 - 1
思路
实际上在升序序列中,我们只需要上个值和当前值,就可以知道当前位置的值是不是我们要找的。所以我们可以只用pre维护中序遍历中的上一节点,如果当前节点值小于上一节点的值,则找到了需要交换的节点,这里有两种可能 只找到一次,上一节点pre和当前节点就是需要交换的节点
找到两次,第一次找到时上一节点pre是需要交换的节点,第二次找到时,当前节点就是需要交换的节点 所以我们可以在第一次找到后先默认pre和当前节点都是要交换的节点,如果有第二次找到,再修改第二个需要交换的节点
代码
//在第一次找到后先默认pre和当前节点都是要交换的节点,如果有第二次找到,再修改第二个需要交换的节点
var recoverTree = function (root) {
let [val1, val2] = [null, null];
let pre = null;
dfs(root);
swap(val1, val2);
return root;
// 中序遍历
function dfs(node) {
if (!node) return;
dfs(node.left);
if (pre === null) pre = node;
else {
if (node.val < pre.val) {
val2 = node;
// 只有第一次找到时,给val1赋值
if (val1 === null) {
val1 = pre;
}
}
pre = node;
}
dfs(node.right);
}
function swap(node1, node2) {
let num = node1.val;
node1.val = node2.val;
node2.val = num;
}
};