248. Strobogrammatic Number III
A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down).
Write a function to count the total strobogrammatic numbers that exist in the range of low <= num <= high.
Example:
Input: low = “50”, high = “100”
Output: 3
Explanation: 69, 88, and 96 are three strobogrammatic numbers.
Note:
Because the range might be a large number, the low and high numbers are represented as string.
方法1:
思路:
首先确定len = 0 和len = 1的一共4个case,然后用递归函数向两端扩展。扩展的终止条件是,current大小已经大于high了,那么一定会越界。否则我们可以定义一个comparator,以string长度排序,如果长度相等,一个字符一个字符比较。我们将符合条件的数字先计入结果,此时注意,虽然“010”这个数字可以继续向下pass扩展,但不是一个valid结果之一,所以还要再判断一次是否是current > 1 && current[0] == ‘0’, 注意当current.size() == 1的时候可以有current = 0。接下来这个current会被继续用hash表里面的数对扩展。
易错点:
- comparator 在定义的时候,a.size() <= b.size():这里之所以有一个等号是因为,我们希望返回闭区间,i.e. low和high本身也应该被返回true。当运行到这一句的时候我们知道ab有可能大小不等,那么直接返回size的比较值,但也有可能完全literally一样,这就是string 中的一个是high或low了,需要返回true。
- 不能用stoi来直接比大小,test case里会出现overflow。
Complexity
Time complexity: O(1)
Space complexity: O(len)
class Solution {
private:
unordered_map<char, char> hash = {{'0','0'}, {'1', '1'}, {'6', '9'}, {'8', '8'}, {'9', '6'}};
bool compare(string & a, string & b) {
if (a.size() == b.size()) {
for (int i = 0; i < a.size(); i++) {
if (a[i] != b[i]) return a[i] < b[i];
}
}
return a.size() <= b.size();
}
public:
int strobogrammaticInRange(string low, string high) {
int res = 0;
strobHelper(low, high, "", res);
strobHelper(low, high, "0", res);
strobHelper(low, high, "1", res);
strobHelper(low, high, "8", res);
return res;
}
void strobHelper(string low, string high, string current, int & res) {
if (high.size() < current.size()) return;
if (compare(low, current) && compare(current, high)) {
if (current.size() == 1 || current.size() > 1 && current[0] != '0') res++;
}
for (auto item: hash) {
strobHelper(low, high, item.first + current + item.second, res);
}
}
};
// 错误的方法,判断何时跳过何时res++出现遗漏
class Solution1 {
private:
unordered_map<char, char> hash = {{'0','0'}, {'1', '1'}, {'6', '9'}, {'8', '8'}, {'9', '6'}};
public:
int strobogrammaticInRange(string low, string high) {
int res = 0;
strobHelper(low, high, "", res);
strobHelper(low, high, "0", res);
strobHelper(low, high, "1", res);
strobHelper(low, high, "8", res);
return res;
}
void strobHelper(string low, string high, string current, int & res) {
if(current.size() >= low.size() && current.size() <= high.size()) {
// 注意这里的写法不对,不能在扩展中途直接消掉"010",因为还可能继续发展成“80108”
if (current.compare(low) < 0 || current.size() > 1 && current[0] == '0' || current.size() == high.size() && current.compare(high) > 0) return;
res++;
// cout << current << endl;
}
if (current.size() + 2 > high.size()) return;
for (auto item: hash) {
strobHelper(low, high, item.first + current + item.second, res);
}
}
};