forked from shuboc/LeetCode-2
-
Notifications
You must be signed in to change notification settings - Fork 1
/
strobogrammatic-number-iii.cpp
96 lines (86 loc) · 3.18 KB
/
strobogrammatic-number-iii.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
// Time: O(5^(n/2))
// Space: O(n)
class Solution {
public:
int strobogrammaticInRange(string low, string high) {
int count = countStrobogrammaticUntil(high, false) -
countStrobogrammaticUntil(low, false) +
isStrobogrammatic(low);
return count >= 0 ? count : 0;
}
int countStrobogrammaticUntil(string num, bool can_start_with_0) {
if (can_start_with_0 && cache.find(num) != cache.end()) {
return cache[num];
}
int count = 0;
if (num.length() == 1) {
for (const auto& c : {'0', '1', '8'}) {
if (num.front() >= c) {
++count;
}
}
cache[num] = count;
return count;
}
for (const auto& kvp : lookup) {
if (can_start_with_0 || kvp.first != '0') {
if (num.front() > kvp.first) {
if (num.length() == 2) { // num is like "21"
++count;
} else { // num is like "201"
count += countStrobogrammaticUntil(string(num.length() - 2, '9'), true);
}
} else if (num.front() == kvp.first) {
if (num.length() == 2) { // num is like 12".
count += num.back() >= kvp.second;
} else {
if (num.back() >= kvp.second) { // num is like "102".
count += countStrobogrammaticUntil(getMid(num), true);
} else if (getMid(num) != string(num.length() - 2, '0')) { // num is like "110".
count += countStrobogrammaticUntil(getMid(num), true) -
isStrobogrammatic(getMid(num));
}
}
}
}
}
if (!can_start_with_0) { // Sum up each length.
for (int i = num.length() - 1; i > 0; --i) {
count += countStrobogrammaticByLength(i);
}
} else {
cache[num] = count;
}
return count;
}
string getMid(const string& num) {
return num.substr(1, num.length() - 2);
}
int countStrobogrammaticByLength(int n) {
switch (n) {
case 1:
return 3; // "0", "1", "8"
case 2:
return 4; // "11", "69", "88", "96"
case 3:
return 4 * 3; // "101", "111", "181", ...
default:
return 5 * countStrobogrammaticByLength(n - 2);
}
}
bool isStrobogrammatic(const string& num) {
const int n = num.size();
for (int i = 0; i <= n - 1 - i; ++i) {
const auto it = lookup.find(num[n - 1 - i]);
if (it == lookup.end() || num[i] != it->second) {
return false;
}
}
return true;
}
private:
const unordered_map<char, char> lookup{{'0', '0'}, {'1', '1'},
{'6', '9'}, {'8', '8'},
{'9', '6'}};
unordered_map<string, int> cache;
};