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?

分析

O(logn)空间的解法是,中序递归遍历,用两个指针存放在遍历过程中碰到的两处逆向的位置。

本题要求O(1)空间,只能用Morris中序遍历。

中序遍历,递归方式

  1. // Recover Binary Search Tree
  2. // 中序遍历,递归
  3. // 时间复杂度O(n),空间复杂度O(logn)
  4. // 本代码仅仅是为了帮助理解题目
  5. class Solution {
  6. public:
  7. void recoverTree(TreeNode *root) {
  8. inOrder( root);
  9. swap(p1->val, p2->val);
  10. }
  11. private:
  12. void inOrder(TreeNode *root) {
  13. if ( root == nullptr ) return;
  14. if ( root->left != nullptr ) inOrder(root->left);
  15. if ( prev != nullptr && root->val < prev->val ) {
  16. if ( p1 == nullptr) {
  17. p1 = prev;
  18. p2 = root;
  19. } else {
  20. p2 = root;
  21. }
  22. }
  23. prev = root;
  24. if ( root->right != nullptr ) inOrder(root->right);
  25. }
  26. TreeNode *p1 = nullptr;
  27. TreeNode *p2 = nullptr;
  28. TreeNode *prev = nullptr;
  29. };

Morris中序遍历

  1. // Recover Binary Search Tree
  2. // Morris中序遍历,时间复杂度O(n),空间复杂度O(1)
  3. class Solution {
  4. public:
  5. void recoverTree(TreeNode* root) {
  6. pair<TreeNode*, TreeNode*> broken;
  7. TreeNode* prev = nullptr;
  8. TreeNode* cur = root;
  9. while (cur != nullptr) {
  10. if (cur->left == nullptr) {
  11. detect(broken, prev, cur);
  12. prev = cur;
  13. cur = cur->right;
  14. } else {
  15. auto node = cur->left;
  16. while (node->right != nullptr && node->right != cur)
  17. node = node->right;
  18. if (node->right == nullptr) {
  19. node->right = cur;
  20. //prev = cur; 不能有这句!因为cur还没有被访问
  21. cur = cur->left;
  22. } else {
  23. detect(broken, prev, cur);
  24. node->right = nullptr;
  25. prev = cur;
  26. cur = cur->right;
  27. }
  28. }
  29. }
  30. swap(broken.first->val, broken.second->val);
  31. }
  32. void detect(pair<TreeNode*, TreeNode*>& broken, TreeNode* prev,
  33. TreeNode* current) {
  34. if (prev != nullptr && prev->val > current->val) {
  35. if (broken.first == nullptr) {
  36. broken.first = prev;
  37. } //不能用else,例如 {0,1},会导致最后 swap时second为nullptr,
  38. //会 Runtime Error
  39. broken.second = current;
  40. }
  41. }
  42. };

相关题目

原文: https://soulmachine.gitbooks.io/algorithm-essentials/content/cpp/binary-tree/traversal/recover-binary-search-tree.html