-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
lowest_common_ancestor.cc
74 lines (63 loc) · 2.66 KB
/
lowest_common_ancestor.cc
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
#include <memory>
#include "binary_tree_node.h"
#include "test_framework/binary_tree_utils.h"
#include "test_framework/generic_test.h"
#include "test_framework/test_failure.h"
#include "test_framework/timed_executor.h"
using std::unique_ptr;
struct Status;
Status LcaHelper(const unique_ptr<BinaryTreeNode<int>>&,
const unique_ptr<BinaryTreeNode<int>>&,
const unique_ptr<BinaryTreeNode<int>>&);
struct Status {
int num_target_nodes;
BinaryTreeNode<int>* ancestor;
};
BinaryTreeNode<int>* Lca(const unique_ptr<BinaryTreeNode<int>>& tree,
const unique_ptr<BinaryTreeNode<int>>& node0,
const unique_ptr<BinaryTreeNode<int>>& node1) {
return LcaHelper(tree, node0, node1).ancestor;
}
// Returns an object consisting of an int and a node. The int field is
// 0, 1, or 2 depending on how many of {node0, node1} are present in
// the tree. If both are present in the tree, when ancestor is
// assigned to a non-null value, it is the LCA.
Status LcaHelper(const unique_ptr<BinaryTreeNode<int>>& tree,
const unique_ptr<BinaryTreeNode<int>>& node0,
const unique_ptr<BinaryTreeNode<int>>& node1) {
if (tree == nullptr) {
return {/*num_target_nodes=*/0, /*ancestor=*/nullptr};
}
auto left_result = LcaHelper(tree->left, node0, node1);
if (left_result.num_target_nodes == 2) {
// Found both nodes in the left subtree.
return left_result;
}
auto right_result = LcaHelper(tree->right, node0, node1);
if (right_result.num_target_nodes == 2) {
// Found both nodes in the right subtree.
return right_result;
}
int num_target_nodes = left_result.num_target_nodes +
right_result.num_target_nodes + (tree == node0) +
(tree == node1);
return {num_target_nodes, num_target_nodes == 2 ? tree.get() : nullptr};
}
int LcaWrapper(TimedExecutor& executor,
const unique_ptr<BinaryTreeNode<int>>& tree, int key0,
int key1) {
const unique_ptr<BinaryTreeNode<int>>& node0 = MustFindNode(tree, key0);
const unique_ptr<BinaryTreeNode<int>>& node1 = MustFindNode(tree, key1);
auto result = executor.Run([&] { return Lca(tree, node0, node1); });
if (!result) {
throw TestFailure("Result can not be nullptr");
}
return result->data;
}
int main(int argc, char* argv[]) {
std::vector<std::string> args{argv + 1, argv + argc};
std::vector<std::string> param_names{"executor", "tree", "key0", "key1"};
return GenericTestMain(args, "lowest_common_ancestor.cc",
"lowest_common_ancestor.tsv", &LcaWrapper,
DefaultComparator{}, param_names);
}