-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRecoverBinarySearchTree.h
134 lines (114 loc) · 4.23 KB
/
RecoverBinarySearchTree.h
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
Author: naiyong, aonaiyong@gmail.com
Date: Sep 30, 2014
Problem: Recover Binary Search Tree
Difficulty: 4
Source: https://oj.leetcode.com/problems/recover-binary-search-tree/
Notes:
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?
swap 3&7
Solution: case A: 1 2 3 4 5 6 7 8 ---------> 1 2 7 4 5 6 3 8
> >
swap 4&5
case B: 1 2 3 4 5 6 7 8 ---------> 1 2 3 5 4 6 7 8
>
1. Recursive In-order Traversal.
Time: O(n), Space: O(n).
2. Iterative In-order Traversal.
Time: O(n), Space: O(n).
3. Morris In-order Traversal.
Time: O(n), Space: O(1).
*/
#ifndef RECOVERBINARYSEARCHTREE_H_
#define RECOVERBINARYSEARCHTREE_H_
#include <climits>
#include <utility>
using std::swap;
#include <stack>
using std::stack;
#include "TreeNode.h"
class Solution {
public:
void recoverTree(TreeNode *root) {
TreeNode *first = nullptr, *second = nullptr;
TreeNode dummy(INT_MIN), *pred = &dummy;
iterativeRecoverTree(root, pred, first, second);
if (first && second)
swap(first->val, second->val);
}
// Recursive In-order Traversal
void recursiveRecoverTree(TreeNode *root, TreeNode *&pred, TreeNode *&first, TreeNode *&second) {
if (!root) return;
recursiveRecoverTree(root->left, pred, first, second);
if (pred->val >= root->val) {
if (!first)
first = pred;
second = root;
}
pred = root;
recursiveRecoverTree(root->right, pred, first, second);
}
// Iterative In-order Traversal
void iterativeRecoverTree(TreeNode *root, TreeNode *&pred, TreeNode *&first, TreeNode *&second) {
stack<TreeNode *> stk;
TreeNode *node = root;
while (node || !stk.empty()) {
if (node) {
stk.push(node);
node = node->left;
}
else {
node = stk.top();
if (pred->val >= node->val) {
if (!first)
first = pred;
second = node;
}
pred = node;
node = node->right;
stk.pop();
}
}
}
// Morris In-order Traversal
void morrisRecoverTree(TreeNode *root, TreeNode *&pred, TreeNode *&first, TreeNode *&second) {
TreeNode *node = root;
while (node) {
if (!node->left) { // left subtree is empty
// process node
if (pred->val > node->val) {
if (!second)
first = pred;
second = node;
}
pred = node;
node = node->right; // advance to right subtree
}
else {
// find the rightmost node of the left subtree
TreeNode *rightMost = node->left;
while (rightMost->right && rightMost->right != node)
rightMost = rightMost->right;
if (!rightMost->right) { // left subtree is to be processed
rightMost->right = node; // make root rightMost's right child
node = node->left; // advance to left subtree
}
else { // left subtree is finished
// process node
if (pred->val > node->val) {
if (!second)
first = pred;
second = node;
}
pred = node;
rightMost->right = nullptr; // restore rightMost's right child to nullptr
node = node->right; // advance to right subtree
}
}
}
}
};
#endif /* RECOVERBINARYSEARCHTREE_H_ */