* 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 recoverTree(TreeNode *root) {
        //一种朴素的想法就是用前序遍历把树里的元素存入vector,排序好后再填回去
        //但这样空间复杂度就是O(n),可以进行优化:正常情况下,通过前序遍历得到的
        //序列是递增的,因此如果发现了在某个位置的数字比前一个小,那么说明这两个
        //数字中有一个被调换了,因此这两个数都先被默认为可能存在“错误”,存入一个
        //vector中。这样的位置在整个前序遍历序列中应该存在两个,全部找到后就可以
        //根据这四个数的大小情况来判断哪两个数被调换了。
        visit(root);
        sort(vcval.begin(), vcval.end());
        for(int i=0;i<vcval.size();i++)
        {
            vcnode[i]->val=vcval[i];
        }
    }
    void visit(TreeNode*root)
    {
        if(root==nullptr||cnt==2)
            return;
        visit(root->left);
        if(root->val<lastval)//找到了一个错误点
        {
            vcnode.push_back(lastnode);
            vcnode.push_back(root);
            vcval.push_back(lastval);
            vcval.push_back(root->val);
            cnt++;
        }
        lastval=root->val;//将当前结点的值作为lastval,用于下一次比较
        lastnode=root;
        visit(root->right);
    }
private:
    int lastval=-9999999;//用于保存上一个结点值
    TreeNode* lastnode=nullptr;//用于保存上一个结点指针
    vector<int> vcval;//用于保存所有可能的错误值
    vector<TreeNode*> vcnode;//用于保存所有可能的错误点
    int cnt=0;//用于记录找到了几组错误点(一共有两组),如果都找到了可以停止遍历
};