248-strobogrammatic-number-iii
Question
https://leetcode.com/problems/strobogrammatic-number-iii/description/
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:
Given low = "50", high = "100", return 3. Because 69, 88, and 96 are three strobogrammatic numbers.
Thought Process
- Construct strobogrammatic number
- We construct the number from length low to high and compare it with the range
- We skip the number that falls outside the range, increase the count othersie
- Time complexity ???
- Space complexity ???
- Count the number in range
- We can use count to speed up the process by avoiding number generation
- The number count is multiply by 5 for every increment on n
- The base cases are n = 1, 2, 3, which the number of stro number is 3, 4, 12
- Count and Subtract
- We can actually use the count difference to get the number of strobogrammtic number in range
- Count(num <= high) - count(num < low)
Solution
class Solution {
private char[][] pair = {{'0', '0'}, {'1', '1'}, {'6', '9'}, {'8', '8'}, {'9', '6'}};
public int strobogrammaticInRange(String low, String high) {
int[] count = new int[1];
for (int i = low.length(); i <= high.length(); i++) {
dfs(low, high, new char[i], 0, i -1, count);
}
return count[0];
}
private void dfs(String low, String high, char[] chars, int l, int r, int[] count) {
if (l > r) {
String num = String.valueOf(chars);
// skip number that is smaller than the low || higher than the high
if (num.length() == low.length() && num.compareTo(low) < 0) return;
if (num.length() == high.length() && num.compareTo(high) > 0) return;
count[0]++;
} else {
for (char[] p : pair) {
chars[l] = p[0];
chars[r] = p[1];
// skip those invalid number starts with 0
if (chars.length != 1 && chars[0] == '0') continue;
// skip odd length number that we overcount for 69 and 96 pair
if (l == r && p[0] != p[1]) continue;
dfs(low, high, chars, l + 1, r - 1, count);
}
}
}
}
class Solution {
private char[][] pair = {{'0', '0'}, {'1', '1'}, {'6', '9'}, {'8', '8'}, {'9', '6'}};
public int strobogrammaticInRange(String low, String high) {
int[] count = new int[1];
for (int i = low.length(); i <= high.length(); i++) {
if (i > low.length() && i < high.length()) count[0] += getCount(i);
else dfs(low, high, new char[i], 0, i -1, count);
}
return count[0];
}
private void dfs(String low, String high, char[] chars, int l, int r, int[] count) {
if (l > r) {
String num = String.valueOf(chars);
// skip number that is smaller than the low || higher than the high
if (num.length() == low.length() && num.compareTo(low) < 0) return;
if (num.length() == high.length() && num.compareTo(high) > 0) return;
count[0]++;
} else {
for (char[] p : pair) {
chars[l] = p[0];
chars[r] = p[1];
// skip those invalid number starts with 0
if (chars.length != 1 && chars[0] == '0') continue;
// skip odd length number that we overcount for 69 and 96 pair
if (l == r && p[0] != p[1]) continue;
dfs(low, high, chars, l + 1, r - 1, count);
}
}
}
private int getCount(int k) {
int res = 4;
if (k % 2 == 1) res *= 3;
for (int i = 1; i < k / 2; i++) {
res *= 5;
}
return res;
}
}
class Solution {
private char[][] pair = {{'0', '0'}, {'1', '1'}, {'6', '9'}, {'8', '8'}, {'9', '6'}};
public int strobogrammaticInRange(String low, String high) {
if (low.length() > high.length()) return 0;
if (low.length() == high.length() && low.compareTo(high) > 0) return 0;
int lowCount = count(low, false);
return count(high, true) - count(low, false);
}
private int count(String num, boolean include) {
int count = 0, n = num.length();
// count all smaller numbers
for (int i = 1; i < n; i++) {
count += getCount(i);
}
// count the equal length;
count += getEqualLength(num.toCharArray(), new char[n], 0, n - 1, include);
return count;
}
private int getEqualLength(char[] num, char[] chars, int l, int r, boolean include) {
if (l > r) {
int compare = compare(chars, num);
if (include) {
return compare <= 0 ? 1 : 0;
} else {
return compare < 0 ? 1: 0;
}
}
int count = 0;
for (char[] p : pair) {
chars[l] = p[0];
chars[r] = p[1];
if (num.length != 1 && chars[0] == '0') continue;
if (l == r && p[0] != p[1]) continue;
count += getEqualLength(num, chars, l + 1, r - 1, include);
}
return count;
}
private int compare(char[] n1, char[] n2) {
for (int i = 0; i < n1.length; i++) {
if (n1[i] < n2[i]) return -1;
else if (n1[i] > n2[i]) return 1;
}
return 0;
}
private int getCount(int k) {
if (k == 1) return 3;
int res = 4;
if (k % 2 == 1) res *= 3;
for (int i = 1; i < k / 2; i++) {
res *= 5;
}
return res;
}
}