• [LeetCode] Recover Binary Search Tree


    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?

    分析:本题做的思路是找到两个需要交换的结点,把两个结点的val值进行交换即可。

    以下两种方法都是LeetCode Discuss中的方法:

    方法1:用递归或栈的方法对树进行中序遍历,当然这种方法不满足O(1)的空间复杂度

    /**
     * Definition for binary tree
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        void recover(TreeNode *root, TreeNode *&pre, TreeNode *&a, TreeNode *&b) {
        if (root)
        {
            recover(root->left, pre, a, b);
    
            if (root->val < pre->val)
            {
                if (!a) a = pre; //a should change once.
                b = root; //b could change twice.
            }
            pre = root;
    
            recover(root->right, pre, a, b);
        }
    }
    void recoverTree(TreeNode *root) {
        if (!root) return;
    
        TreeNode p(numeric_limits<int>::min());
        TreeNode *a, *b, *pre;
        a = b = 0;
        pre = &p;
        recover(root, pre, a, b);
        if (a && b)
        {
            swap(a->val, b->val);
        }
        return;
    }
    };

    方法2:morris traversal的方法,这种方法借鉴线索二叉树的方法,即不用递归和栈,用改变树的关键结点的指向的方法来遍历二叉树,使用完指向信息后,再将树恢复。参见http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/

    class Solution {
    public:
        void recoverTree(TreeNode *root) {
            if (root == NULL) return;
            TreeNode * ptr, *pred, * current;
            TreeNode * pred1, * cur1, * pred2, * cur2;
    
            current = root; ptr = pred = NULL;
            pred1 = cur1 = pred2 = cur2 = NULL;
    
            while (current != NULL){
                if (current->left == NULL){
                    pred = current;
                    current = current->right;
                }else{
                    ptr = current->left;
                    while (ptr->right != NULL && ptr->right != current)
                        ptr = ptr->right;
                    if (ptr->right == NULL){//构造线索二叉树
                        ptr->right = current;
                        current = current->left;
                    }else{                  //把线索二叉树恢复成原先的二叉树
                        ptr->right = NULL;
                        pred = current;
                        current = current->right;
                    }
                }//end if
                if (pred != NULL && current != NULL && pred->val > current->val){//找到待交换的2个数
                    if (pred1 == NULL) { 
                        pred1 = pred; 
                        cur1 = current;
                    }
                    else {
                        pred2 = pred; 
                        cur2 = current; 
                    } 
                }//end if
            }//end if
    
            int tmp;
            if (pred1 != NULL && cur2 != NULL){//pred1和cur2交换
                tmp = pred1->val;
                pred1->val = cur2->val;
                cur2->val = tmp;
            }
            else{                            //pred1和cur1交换
                tmp = pred1->val; 
                pred1->val = cur1->val; 
                cur1->val = tmp; 
            } 
        }
    };

    把原理弄清楚,自己实现一下。

  • 相关阅读:
    应用环境配置记录
    【C#】Dictionary通过value获取对应的key值
    DevExpress 之 GridControl 自定义列(转)
    C#中gridView常用属性和技巧介绍(转)
    【643】cv2.imread() 函数
    【642】Python 实现膨胀、腐蚀、提取边线
    【639】keras 中 fit_generator 的 数据生成器
    【638】keras 多输出模型【实战】
    【637】一个图片两个标注的图像增强
    别自嗨了!想做新生代农民工,你还不够格。。
  • 原文地址:https://www.cnblogs.com/Xylophone/p/3893948.html
Copyright © 2020-2023  润新知