题目描述:
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?
使用O(n)辅助空间的方法就是使用中序遍历从BST中获得一个有序递增的序列, 但是其中有两个元素的位置交换了. 被交换的元素的特征就是前一个元素大于后一个元素, 找到这样两个元素再把它们交换回来即可, 如果只找到了一个这样的元素, 说明是相邻的两个元素交换了.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
   | 
 
 
 
 
 
 
 
  class Solution {     deque<TreeNode*> seq; public:     void recoverTree(TreeNode* root) {         inOrder(root);         vector<int> mistakeNodes;         for(int i = 0; i < seq.size() - 1; i++){             if(seq[i]->val > seq[i + 1]->val){                 mistakeNodes.push_back(i);             }         }         if(mistakeNodes.size() == 1){             swap(seq[mistakeNodes[0]]->val, seq[mistakeNodes[0] + 1]->val);         }         else{             swap(seq[mistakeNodes[0]]->val, seq[mistakeNodes[1] + 1]->val);         }     }          void inOrder(TreeNode *root){         if(root == nullptr) return;         inOrder(root->left);         seq.push_back(root);         inOrder(root->right);     } };
 
  | 
 
而把这一思路推广到不使用辅助空间, 很容易就可以发现我们并不需要一个完整的序列, 只需要相邻两个值的大小关系, 所以我们只要在遍历过程中维持两个节点值即可. 另外由于我们没有完整的序列, 所以在mistakeNodes中要同时保存前一个元素比后一个元素大的这两个元素, 因为对于被交换的较小值来说, 它在后一个元素的位置, 而对于较大值来说, 它位于前一个元素的位置. 当然也可以通过判断mistakeNodes中是否已经有元素来避免同时保存.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
   | 
 
 
 
 
 
 
 
  class Solution {     vector<TreeNode*> mistakeNodes;     vector<TreeNode*> tmpNodes; public:     void recoverTree(TreeNode* root) {         tmpNodes.resize(2);         inOrder(root);         if(mistakeNodes.size() == 2){             swap(mistakeNodes[0]->val, mistakeNodes[1]->val);         }         else{             swap(mistakeNodes[0]->val, mistakeNodes[3]->val);         }     }          void inOrder(TreeNode *root){         if(root == nullptr || mistakeNodes.size() == 4) return ;         inOrder(root->left);         tmpNodes[0] = tmpNodes[1];         tmpNodes[1] = root;         if(tmpNodes[0] && tmpNodes[0]->val > tmpNodes[1]->val){             mistakeNodes.push_back(tmpNodes[0]);             mistakeNodes.push_back(tmpNodes[1]);         }         inOrder(root->right);     } };
 
  |