• 【Recover Binary Search Tree】cpp


    题目:

    Two elements of a binary search tree (BST) are swapped by mistake.

    Recover the tree without changing its structure.

    Note:
    A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?

    confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.

    代码:

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        void recoverTree(TreeNode* root) {
                if (!root) return;
                TreeNode *pre, *curr, *first=NULL, *second=NULL;
                stack<TreeNode *> sta;
                TreeNode *dummy = new TreeNode(INT_MIN);
                dummy->left = root;
                pre = dummy;
                curr = root;
                while ( !sta.empty() || curr )
                {
                    if (curr){
                        sta.push(curr);
                        curr = curr->left;
                    }
                    else{
                        curr = sta.top();
                        sta.pop();
                        if ( !first ){
                            if ( pre->val > curr->val ){
                                first = pre;
                                second = curr;
                            }
                        }
                        else{
                            if ( curr->val < pre->val ){
                                second = curr;
                                break;
                            }
                        }
                        pre = curr;
                        curr = curr->right;
                    }
                }
                std::swap(first->val, second->val);
        }
    };

    tips:

    二叉查找树的中序遍历就是从小到大的输出(http://zh.wikipedia.org/wiki/二元搜尋樹)。

    即从中序遍历的结果中找到两个需要交换的点。

    为了简便,这里设定了虚根节点(初始化值为INT_MIN)保证不影响中序遍历的结果。具体的思想都参考的(http://www.cnblogs.com/TenosDoIt/p/3445682.html)。

    通过这道题回顾了一下中序遍历的方法,并纠正了之前的中序遍历的一种自毁型的代码

    http://www.cnblogs.com/xbf9xbf/p/4501655.html

    在上面这道题中,写了一个自毁型的中序遍历代码(即中序遍历结束后,整个二叉树的所有节点都断了)。

    在本道题中一开始沿用了这种自毁型的中序遍历代码,结果就可想而知了。通过这个点,给自己提个醒:以后再涉及到遍历这类的代码,尽量不要再写这种遍历一次就毁坏了数据结构的代码了。 

    ===========================================

    第二次过这道题,直接学习的原来的代码。AC之后弄清楚了两个点:

    (1)中序遍历是个模板,对BST的操作很多都依赖中序遍历。所以不管有没有first和second都要注意把中序遍历的代码写全了

    (2)为什么找到第一个是first=pre而找到第二个是second=curr呢?曾就这个问题纠结过,后来猜测背后的思路可能是这样的:

       由于BST的两个节点位置错乱了,那么中序遍历必然有前面的节点要大于后面的。因此找到第一个不符合BST条件的,pre肯定是first;找到第二个不符合条件的curr肯定是second。

       另外还有一种特殊情况,就是被错位的两个点是挨着的,这样就更直接了。pre肯定是frist,curr肯定是second。

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        void recoverTree(TreeNode* root) {
                stack<TreeNode*> sta;
                TreeNode* first=NULL;
                TreeNode* second=NULL;
                TreeNode dummpy(INT_MIN);
                dummpy.left = root;
                TreeNode* pre = &dummpy;
                TreeNode* curr = root;
                while ( !sta.empty() || curr )
                {
                    if ( curr )
                    {
                        sta.push(curr);
                        curr = curr->left;
                    }
                    else
                    {
                        curr = sta.top();
                        sta.pop();
                        if ( !first )
                        {
                            if (curr->val<pre->val)
                            {
                                first = pre;
                                second = curr;
                            }
                        }
                        else
                        {
                            if ( curr->val<pre->val)
                            {
                                second = curr;
                                break;
                            }
                        }
                        pre = curr;
                        curr = curr->right;
                    }
                }
                std::swap(first->val, second->val);
        }
    };

    ============================================================

    第三次过这道题,本来不想粘代码了,但前几次的代码实在太冗余了,于是贴一版新的。

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        void recoverTree(TreeNode* root) {
            stack<TreeNode*> sta;
            TreeNode *pre = new TreeNode(INT_MIN);
            TreeNode *curr = root;
            TreeNode *n1=NULL, *n2=NULL;
            while ( !sta.empty() || curr )
            {
                if ( curr )
                {
                    sta.push(curr);
                    curr = curr->left;
                }
                else
                {
                    curr = sta.top(); sta.pop();
                    if ( pre->val > curr->val )
                    {
                        if ( !n1 )
                        {
                            n1 = pre;
                            n2 = curr;
                        }
                        else
                        {
                            n2 = curr;
                            break;
                        }
                    }
                    pre = curr;
                    curr = curr->right;
                }
            }
            if (n1) swap(n1->val, n2->val);
        }
    };
  • 相关阅读:
    第18章 图元文件_18.1 老式图元文件格式(wmf)
    第17章 文本和字体_17.6 一些有趣和新奇的内容
    第17章 文本和字体_17.5 设置段落格式
    第17章 文本和字体_17.4 字体枚举
    第17章 文本和字体_17.3 逻辑字体
    第17章 文本和字体_17.1-17.2 简单文本输出、 字体的背景知识
    第16章 调色板管理器_16.4 一个DIB位图库的实现(2)
    第16章 调色板管理器_16.4 一个DIB位图库的实现(1)
    第16章 调色板管理器_16.3 调色板和现实世界中的图像
    第16章 调色板管理器_16.2 调色板动画
  • 原文地址:https://www.cnblogs.com/xbf9xbf/p/4504681.html
Copyright © 2020-2023  润新知