Problem Description:
A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down).
Write a function to determine if a number is strobogrammatic. The number is represented as a string.
For example, the numbers “69”, “88”, and “818” are all strobogrammatic.
Analysis :
You will find that there are only five digit meet the requirement. 0, 1, 6, 8, 9;
class Solution {
public:
bool isStrobogrammatic(string num) {
table['0'] = '0';
table['1'] = '1';
table['6'] = '9';
table['8'] = '8';
table['9'] = '6';
int n = num.length();
for (int l = 0, r = n - 1; l <= r; l++, r--)
if (table.find(num[l]) == table.end() || table[num[l]] != num[r])
// whether the number is in the table or the two numbers in front and end are symmetric.
return false;
return true;
}
private:
unordered_map<char, char> table;
};
Follow up:
Find all strobogrammatic numbers that are of length = n.
This link is a good reference
Analysis :
We build the string from inside out from middle. if n is an even number, the middle is “”, else the middle could be one of the “0”, “1”, “8”. Then we keeping add numbers in the both side of the middle. PS: we have to skip the number that leading with 0.
Code:
recursive one using DFS
void dfs (vector<string>& res, string temp, vector<string> & pair, int i, int j)
{
if (i > j)
{
if (temp[0] != '0' || temp.size() == 1)
{
res.push_back(temp);
return;
}
}
for (int x = 0; x < 5; ++x)
{
temp[i] = pair[x][0];
temp[j] = pair[x][1];
if (i == j && pair[x][0] == pair[x][1] || i < j)
dfs(res, temp, pair, i + 1, j - 1);
}
}
vector<string> Strobogrammatic_print(int n)
{
vector<string> pair = {"00", "11", "69", "88", "96"};
string temp(n, '0');
vector <string> res;
dfs (res,temp, pair, 0, n - 1);
return res;
}
Iterative one:
// 0, 1, 8, 9,6
vector<string> Strobogrammatic_print(int n)
{
vector<string> res;
if (n & 1) res ={"0", "1", "8"};
else res = {""};
vector <string> pair = {"00", "11", "69", "88", "96"};
for (; n > 1; n -= 2)
{
vector<string> temp;
for (string rel : res)
for (int i = n < 4; i < pair.size(); i++)
temp.push_back(pair[i][0] + rel + pair[i][1]);
res = move(temp);
}
// while (n > 1) {
// n -= 2;
// vector<string> temp;
// for (string strobo : strobos)
// for (int i = n < 2; i < m; i++)
// temp.push_back(bases[i][0] + strobo + bases[i][1]);
// strobos = move(temp);
// }
return res;
}
Follow up:
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.
For example, given low = 50, high = 100, return 3. Becase 69, 88, and 96 are three strobogrammatic numbers.
Construct the string from l(low.size()) to u (high.size()) and increase count when s is between low and high. build the stos pairs from outside to inside until lo > hi;
You may refer to this link for a very readable code
unordered_map<char, char> mp;
mp = {{'0', '0'}, {'1','1'}, {'6','9'}, {'8','8'}, {'9','6'}};
int findStrobogrammaticNumber(string low, string high) {
int ans = 0, l = low.size(), u = high.size();
for (int i = l; i <= u; ++i){
string temp(i, ' ');
strobogrammaticCount(temp, ans, low, high, 0, i - 1);
}
return ans;
}
// dfs
void strobogrammaticCount(string temp, int & ans, string & low, string & high, int lo, int hi)
{
if (lo > hi)
{
if ((temp[0] != '0' || temp.size() == 1) && temp.compare(low) > 0 && temp.compare(high) < 0)
ans++;
return;
}
for (auto m : mp)
{
temp[lo] = m.first;
temp[hi] = m.second;
if (lo == hi && m.first == m.second || lo < hi)
strobogrammaticCount(temp, ans, low, high, lo + 1, hi - 1);
}
}