持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情
一.题目:
99. 恢复二叉搜索树 给你二叉搜索树的根节点
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
二、思路分析:
还是相同的套路,根据题目的提示完成相应的作答。题目中给出二叉搜索树根节点root,里面恰好只有两个节点的值被错误地交换,这句话给了我们两个信息:1.我们只需要找出破坏二叉树搜索的两个节点即可,而且是有且仅有两个。2.还告诉了我们一个隐含信息,即我们不用通过新增节点加删除节点的操作完成交换,仅仅是交换两个节点的值即可。所以基本思路为:
- 我们需要定义两个变量来接收我们需要交换的两个节点的信息。还需要一个变量来存储我们目前遍历的节点的上一位置。
- 因为是
二叉搜索树,它的中序遍历一定是有序的,所以我们借助这一点对二叉搜索树进行遍历,发现不符合的就找到了我们需要找出的节点。这里需要注意的是,第一个不符合结构的一定是最开始找到的那个节点,而node_two则需要我们不断地找寻最后符合条件的。 - 最后我们进行值的交换即可完成题目的解答。
三、代码:
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
/**
Do not return anything, modify root in-place instead.
*/
function recoverTree(root: TreeNode | null): void {
let node_one: TreeNode = null;
let node_two: TreeNode = null;
//用一个变量标记先前的位置
let pre: TreeNode = new TreeNode(Number.MIN_SAFE_INTEGER);
function inorderTraverse(root: TreeNode | null): void{
//找到交换的两个节点
if(root === null) return;
inorderTraverse(root.left);
//中序遍历位置
if(root.val < pre.val){
//找到第一个节点的位置
if(node_one === null){
node_one = pre;
}
//一直找找到最小的为止
node_two = root;
}
pre = root;
inorderTraverse(root.right);
}
inorderTraverse(root);
// 进行节点值的交换
let temp:number = node_one.val;
node_one.val = node_two.val;
node_two.val = temp;
};
四、总结:
对于二叉搜索树我们需要牢记它的中序遍历一定是有序的,都是遵循
左小右大的规则,利用好这一点那么这道题目的思路就很清晰了。
ps:祝大家端午节安康,虽然是迟来的祝福~~~