(Leetcode 99) Recover Binary Search Tree(恢复二叉排序树BST)

题目原文: Two elements of a binary search tree (BST) are swapped by
mistake.
Recover the tree without changing its structure

题意解释

  • 大家都知道,二叉排序树BST的中序序列是由小到大排序的,而如果BST的两个节点交换后,其中序遍历序列一定不再是由小到大排序的。

例如原来二叉树是 “214##35”,交换节点2和3之后变成了314##25,如下图所示:

交换前:(中序遍历序列:12345
这里写图片描述
交换后:(中序遍历序列:13245
这里写图片描述

思路
用中序遍历序列的递归方法可以解决该问题,我们先写一个简单的中序遍历的递归代码:

void traverse(TreeNode *root){
    if(root == NULL)
        return ;
    traverse(root->left);
    //Do something
    traverse(root->right);
}

在 Do something 部分可以完成诸如输出,入栈等操作。那么对于这道题目来说,我们在Do something部分将要完成的工作是找到 fristElementsecondElement,即第一个逆序的节点和第二个逆序的节点。

中序遍历序列是13245
我们比较每个节点与其中序遍历的下一个节点,我们可以发现,3是第一个要交换的节点firstElement,因为3应该小于后一个节点,而2是第二个要交换的节点secondElement,因为2应该大于前一个节点。

我们定义的前一个节点后一个节点是按照中序遍历序列定义的。

我们定义三个变量firstElement,secondElement,preElement,分别存储要交换的两个节点和当前遍历到的节点的中序前驱。

代码如下(请注意注释部分)


class Solution{
public:
    //firstElement和secondElement分别代表第一个逆序的位置和第二个逆序的位置
    //第一步需要在中序遍历序列中找到这两个位置,第二步需要交换这两个位置
    TreeNode *firstElement; 
    TreeNode *secondElement;
    TreeNode *preElement;   //代表当前遍历的位置的中序前驱节点,先赋一个最小值

    //traverse函数负责找到两个逆序的位置,随后用swap函数将这两个位置进行交换
    void recoverTree(TreeNode* root) {
        traverse(root);
        swap(firstElement->val, secondElement->val);
    }
    //中序遍历序列找到两个逆序的位置
    void traverse(TreeNode *root){
        if(root == NULL)
            return ;
        //中序遍历左子树
        traverse(root->left);

        if(preElement != NULL){
            //查看是否逆序,如果逆序,给firstElement和secondElement赋值
            if(firstElement == NULL && preElement->val > root->val){
                //当firstElement还没有被赋值,第一个逆序位置是pre节点
                firstElement = preElement;
            }
            if(firstElement != NULL && preElement->val > root->val){
                //当firstElement已经被赋值,第二个逆序位置是root节点
                secondElement = root;
            }
        }
        preElement = root;   //更新preElement的值

        //中序遍历右子树
        traverse(root->right);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值