Skip to content

Commit d89e965

Browse files
authored
Create move-sub-tree-of-n-ary-tree.cpp
1 parent f27e743 commit d89e965

File tree

1 file changed

+239
-0
lines changed

1 file changed

+239
-0
lines changed

C++/move-sub-tree-of-n-ary-tree.cpp

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
// Time: O(n)
2+
// Space: O(h)
3+
4+
/*
5+
// Definition for a Node.
6+
class Node {
7+
public:
8+
int val;
9+
vector<Node*> children;
10+
11+
Node() {}
12+
13+
Node(int _val) {
14+
val = _val;
15+
}
16+
17+
Node(int _val, vector<Node*> _children) {
18+
val = _val;
19+
children = _children;
20+
}
21+
};
22+
*/
23+
24+
// one pass solution without recursion
25+
class Solution {
26+
public:
27+
Node* moveSubTree(Node* root, Node* p, Node* q) {
28+
unordered_map<Node *, Node *> lookup;
29+
const auto& is_ancestor = iter_find_parents(root, nullptr, p, q, false, &lookup);
30+
if (lookup.count(p) && lookup[p] == q) {
31+
return root;
32+
}
33+
q->children.emplace_back(p);
34+
if (!is_ancestor) {
35+
lookup[p]->children.erase(find(begin(lookup[p]->children), end(lookup[p]->children), p));
36+
} else {
37+
lookup[q]->children.erase(find(begin(lookup[q]->children), end(lookup[q]->children), q));
38+
if (p == root) {
39+
root = q;
40+
} else {
41+
*find(begin(lookup[p]->children), end(lookup[p]->children), p) = q;
42+
}
43+
}
44+
return root;
45+
}
46+
47+
private:
48+
bool iter_find_parents(Node *node, Node *parent, Node *p, Node *q,
49+
bool is_ancestor,
50+
unordered_map<Node *, Node *> *lookup) {
51+
vector<tuple<int, Node *, Node *, bool, int>> stk = {tuple(1, node, parent, is_ancestor, -1)};
52+
while (!stk.empty()) {
53+
const auto [step, node, parent, is_ancestor, i] = stk.back(); stk.pop_back();
54+
if (step == 1) {
55+
if (node == p || node == q) {
56+
(*lookup)[node] = parent;
57+
if (lookup->size() == 2) {
58+
return is_ancestor;
59+
}
60+
}
61+
stk.emplace_back(2, node, parent, is_ancestor, node->children.size() - 1);
62+
} else {
63+
if (i < 0) {
64+
continue;
65+
}
66+
stk.emplace_back(2, node, parent, is_ancestor, i - 1);
67+
stk.emplace_back(1, node->children[i], node, is_ancestor || node == p, -1);
68+
}
69+
}
70+
assert(false);
71+
return false;
72+
}
73+
};
74+
75+
// Time: O(n)
76+
// Space: O(h)
77+
// one pass solution with recursion
78+
class Solution_Recu {
79+
public:
80+
Node* moveSubTree(Node* root, Node* p, Node* q) {
81+
unordered_map<Node *, Node *> lookup;
82+
const auto& [_, is_ancestor] = find_parents(root, nullptr, p, q, false, &lookup);
83+
if (lookup.count(p) && lookup[p] == q) {
84+
return root;
85+
}
86+
q->children.emplace_back(p);
87+
if (!is_ancestor) {
88+
lookup[p]->children.erase(find(begin(lookup[p]->children), end(lookup[p]->children), p));
89+
} else {
90+
lookup[q]->children.erase(find(begin(lookup[q]->children), end(lookup[q]->children), q));
91+
if (p == root) {
92+
root = q;
93+
} else {
94+
*find(begin(lookup[p]->children), end(lookup[p]->children), p) = q;
95+
}
96+
}
97+
return root;
98+
}
99+
100+
private:
101+
pair<bool, bool> find_parents(Node *node, Node *parent, Node *p, Node *q,
102+
bool is_ancestor,
103+
unordered_map<Node *, Node *> *lookup) {
104+
if (node == p || node == q) {
105+
(*lookup)[node] = parent;
106+
if (lookup->size() == 2) {
107+
return {true, is_ancestor};
108+
}
109+
}
110+
for (const auto& child : node->children) {
111+
const auto& [found, result] = find_parents(child, node, p, q, is_ancestor || node == p, lookup);
112+
if (found) {
113+
return {true, result};
114+
}
115+
}
116+
return {false, false};
117+
}
118+
};
119+
120+
// Time: O(n)
121+
// Space: O(h)
122+
// two pass solution without recursion
123+
class Solution2 {
124+
public:
125+
Node* moveSubTree(Node* root, Node* p, Node* q) {
126+
unordered_map<Node *, Node *> lookup;
127+
iter_find_parents(root, nullptr, p, q, &lookup);
128+
if (lookup.count(p) && lookup[p] == q) {
129+
return root;
130+
}
131+
q->children.emplace_back(p);
132+
if (!iter_is_ancestor(p, q)) {
133+
lookup[p]->children.erase(find(begin(lookup[p]->children), end(lookup[p]->children), p));
134+
} else {
135+
lookup[q]->children.erase(find(begin(lookup[q]->children), end(lookup[q]->children), q));
136+
if (p == root) {
137+
root = q;
138+
} else {
139+
*find(begin(lookup[p]->children), end(lookup[p]->children), p) = q;
140+
}
141+
}
142+
return root;
143+
}
144+
145+
private:
146+
void iter_find_parents(Node *node, Node *parent, Node *p, Node *q,
147+
unordered_map<Node *, Node *> *lookup) {
148+
vector<tuple<int, Node *, Node *, int>> stk = {tuple(1, node, parent, -1)};
149+
while (!stk.empty()) {
150+
const auto [step, node, parent, i] = stk.back(); stk.pop_back();
151+
if (step == 1) {
152+
if (node == p || node == q) {
153+
(*lookup)[node] = parent;
154+
if (lookup->size() == 2) {
155+
return;
156+
}
157+
}
158+
stk.emplace_back(2, node, parent, node->children.size() - 1);
159+
} else {
160+
if (i < 0) {
161+
continue;
162+
}
163+
stk.emplace_back(2, node, parent, i - 1);
164+
stk.emplace_back(1, node->children[i], node, -1);
165+
}
166+
}
167+
}
168+
169+
bool iter_is_ancestor(Node *node, Node *q) {
170+
vector<tuple<int, Node *, int>> stk = {tuple(1, node, -1)};
171+
while (!stk.empty()) {
172+
const auto [step, node, i] = stk.back(); stk.pop_back();
173+
if (step == 1) {
174+
stk.emplace_back(2, node, node->children.size() - 1);
175+
} else {
176+
if (i < 0) {
177+
continue;
178+
}
179+
if (node->children[i] == q) {
180+
return true;
181+
}
182+
stk.emplace_back(2, node, i - 1);
183+
stk.emplace_back(1, node->children[i], -1);
184+
}
185+
}
186+
return false;
187+
}
188+
};
189+
190+
// Time: O(n)
191+
// Space: O(h)
192+
// two pass solution with recursion
193+
class Solution2_Recu {
194+
public:
195+
Node* moveSubTree(Node* root, Node* p, Node* q) {
196+
unordered_map<Node *, Node *> lookup;
197+
find_parents(root, nullptr, p, q, &lookup);
198+
if (lookup.count(p) && lookup[p] == q) {
199+
return root;
200+
}
201+
q->children.emplace_back(p);
202+
if (!is_ancestor(p, q)) {
203+
lookup[p]->children.erase(find(begin(lookup[p]->children), end(lookup[p]->children), p));
204+
} else {
205+
lookup[q]->children.erase(find(begin(lookup[q]->children), end(lookup[q]->children), q));
206+
if (p == root) {
207+
root = q;
208+
} else {
209+
*find(begin(lookup[p]->children), end(lookup[p]->children), p) = q;
210+
}
211+
}
212+
return root;
213+
}
214+
215+
private:
216+
bool find_parents(Node *node, Node *parent, Node *p, Node *q, unordered_map<Node *, Node *> *lookup) {
217+
if (node == p || node == q) {
218+
(*lookup)[node] = parent;
219+
if (lookup->size() == 2) {
220+
return true;
221+
}
222+
}
223+
for (const auto& child : node->children) {
224+
if (find_parents(child, node, p, q, lookup)) {
225+
return true;
226+
}
227+
}
228+
return false;
229+
}
230+
231+
bool is_ancestor(Node *node, Node *q) {
232+
for (const auto& child : node->children) {
233+
if (child == q || is_ancestor(child, q)) {
234+
return true;
235+
}
236+
}
237+
return false;
238+
}
239+
};

0 commit comments

Comments
 (0)