-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSolution.cpp
108 lines (90 loc) · 2.65 KB
/
Solution.cpp
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
#include <algorithm>
#include <array>
#include <bitset>
#include <climits>
#include <cmath>
#include <functional>
#include <iostream>
#include <memory>
#include <queue>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// Only up to 10^8 is necessary
constexpr std::array<int, 9> powOfTen = []() {
std::array<int, 9> result{};
result[0] = 1;
for (int i = 1; i < 9; ++i) {
result[i] = result[i - 1] * 10;
}
return result;
}();
struct TrieNode {
bool isEnd;
std::array<std::unique_ptr<TrieNode>, 10> children;
TrieNode() : children{}, isEnd{false} {}
};
class Trie {
private:
// Shared instead of unique because an iterator needs to copy the pointer
std::unique_ptr<TrieNode> root;
// No need to handle x = 0. Constraints guarantee x is positive.
inline int numDigits(const int x) const {
return static_cast<int>(std::floor(std::log10(x)) + 1);
}
public:
Trie() : root(std::make_unique<TrieNode>()) {}
void insert(const int x) {
// No need to delete at the end of the function. Iter does not own the
// pointer.
TrieNode* iter{root.get()};
const int n = numDigits(x);
// Iterate from most significant, left-most digit to least significant.
for (int i = n - 1; i >= 0; --i) {
const int digit = (x / powOfTen[i]) % 10;
if (!iter->children[digit]) {
iter->children[digit] = std::make_unique<TrieNode>();
}
iter = iter->children[digit].get();
}
iter->isEnd = true;
}
int findLongestPrefix(const int y) const {
int result{0};
TrieNode* iter{root.get()};
const int n = numDigits(y);
for (int i = n - 1; i >= 0; --i) {
const int digit = (y / powOfTen[i]) % 10;
if (!iter->children[digit]) {
break;
}
iter = iter->children[digit].get();
++result;
}
return result;
}
};
using namespace std;
class Solution {
public:
int longestCommonPrefix(vector<int>& arr1, vector<int>& arr2) {
// positive integers in arr1 and arr2
// Find largest common prefix all of pairs. At least O(nm) to compare
// each element of arr1 to each element of arr2. isPrefix check should be
// O(1) time, since each integer is only 32 bits long, or 9 digits long,
// given the constraints 1 <= arr[i] <= 10^8
// Can we do better than O(nm)?
// Lexicographical order would allow us to compare prefixes quicker.
Trie prefixes{};
for (const int& num : arr1) {
prefixes.insert(num);
}
int longestPrefix = 0;
for (const int& num : arr2) {
longestPrefix = std::max(longestPrefix, prefixes.findLongestPrefix(num));
}
return longestPrefix;
}
};