zoukankan      html  css  js  c++  java
  • [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?

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


    OJ's Binary Tree Serialization:

    The serialization of a binary tree follows a level order traversal, where '#' signifies a path terminator where no node exists below.

    Here's an example:

       1
      / 
     2   3
        /
       4
        
         5
    
    The above binary tree is serialized as"{1,2,3,#,#,4,#,#,5}".
     
    最简单的办法应该是,中序遍历二叉树,将各个结点的值存储在一维向量中,然后进行一次赋值操作。这种方法对任意个数的节点错乱都实用。
     详情见Grangyang的博客
     1 /**
     2  * Definition for binary tree
     3  * struct TreeNode {
     4  *     int val;
     5  *     TreeNode *left;
     6  *     TreeNode *right;
     7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     8  * };
     9  */
    10 class Solution {
    11 public:
    12     void recoverTree(TreeNode *root) 
    13     {
    14         vector<TreeNode *> treeNode;
    15         vector<int> nodeVal;
    16         inoder(root,treeNode,nodeVal);
    17         sort(nodeVal.begin(),nodeVal.end());
    18         for(int i=0;i<treeNode.size();++i)
    19             treeNode[i]->val=nodeVal[i];
    20     }
    21 
    22     void inoder(TreeNode *root,vector<TreeNode *> &treeNode,vector<int> &nodeVal)
    23     {
    24         if(root==NULL)  return;
    25         inoder(root->left,treeNode,nodeVal);
    26         treeNode.push_back(root);
    27         nodeVal.push_back(root->val);
    28         inoder(root->right,treeNode,nodeVal);
    29     }
    30 };

     方法二:

    用三个指针,w1,w2分别指向第一、二个错误的地方。pre指向当前结点中序遍历中的前一个结点。因有两个结点交换了,所以二叉树的中序遍历中会出现违背有序的情况,一、即中序遍历中相邻的结点被交换,则违背有序的情况出现一次,如132456;二、中序遍历中不相邻的两个结点的值被交换,则出现两次违背有序情况,如153426.针对情况1,pre=3,w1=pre即为3,w2=root,即为2,在后续的遍历中没有违背有序的情况,所以交换w1和w2即可;针对情况2,找到第一个错误点后,w1 !=NULL了,所以,第二个错误点w2=root,第一逆序的前结点,第二逆序的后结点,交换两者即可。

     1 /**
     2  * Definition for binary tree
     3  * struct TreeNode {
     4  *     int val;
     5  *     TreeNode *left;
     6  *     TreeNode *right;
     7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     8  * };
     9  */
    10 class Solution {
    11 public:
    12     TreeNode *w1,*w2,*pre;
    13     void recoverTree(TreeNode *root) 
    14     {
    15         if(root==NULL)  return;
    16         w1=w2=pre=NULL;
    17         find(root);
    18         swap(w1->val,w2->val);
    19     }
    20     void find(TreeNode *root)
    21     {
    22         if(root==NULL)  return;
    23         find(root->left);
    24         if(pre&&pre->val > root->val)
    25         {
    26             if(w1==NULL)    //情况1
    27             {
    28                 w1=pre;
    29                 w2=root;
    30             }
    31             else            //情况2
    32                 w2=root;
    33         }
    34         pre=root;
    35         find(root->right);
    36     }
    37 };

    方法三

    层次遍历中的Mirror方法,修改部分得到。真正的O(1)。

    // Now O(1) space complexity
    class Solution {
    public:
        void recoverTree(TreeNode *root) {
            TreeNode *first = NULL, *second = NULL, *parent = NULL;
            TreeNode *cur, *pre;
            cur = root;
            while (cur) {
                if (!cur->left) {
                    if (parent && parent->val > cur->val) {
                        if (!first) first = parent;
                        second = cur;
                    }
                    parent = cur;
                    cur = cur->right;
                } else {
                    pre = cur->left;
                    while (pre->right && pre->right != cur) pre = pre->right;
                    if (!pre->right) {
                        pre->right = cur;
                        cur = cur->left;
                    } else {
                        pre->right = NULL;
                        if (parent->val > cur->val) {
                            if (!first) first = parent;
                            second = cur;
                        }
                        parent = cur;
                        cur = cur->right;
                    }
                }
            }
            if (first && second) swap(first->val, second->val);
        }
    };
  • 相关阅读:
    读取XML字符串到临时表
    Golang学习笔记
    Golang环境配置Centos
    IntelliJ Idea 常用快捷键列表
    Elasticsearch的Groovy Script自定义评分检索
    MSSQL读取xml字符串到临时表
    通过反射给对象属性动态赋值总结(含可空属性)
    。。。。。
    指定位置输出函数
    DBhelper
  • 原文地址:https://www.cnblogs.com/love-yh/p/7003660.html
Copyright © 2011-2022 走看看