刚看这一题的时候觉得是要返回number,以为是有什么取巧的方式,思前想后发现取巧的方式太复杂,看了一下别人的答案,结果发现还是要用穷举加过滤。也就是说大家的解基本都是能够得到全部解集而不仅仅是一个数字作为答案的。只能说我想多了。
既然是穷举加过滤,那么方法其实不是很复杂,是Strobogrammatic Number II的一种延伸。
在Strobogrammatic Number II里面,我们可以得到某个长度的解集。而这一题,我们就可以利用这个解。得到不同长度的解集,然后在low这个长度上和high这个长度上进行字符串比较从而过滤掉范围外的答案。
举个例子,50 到 10000, 那么我们就有了四个长度: 2, 3, 4, 5
我们通过Strobogrammatic Number II 的方式进行求解集,然后再长度2和5的时候分别与low或者high进行字符串比较即可。
public int strobogrammaticInRange(String low, String high) {
if (low.length() > high.length() || (low.length() == high.length() && low.compareTo(high) > 0)) return 0;
Map<Character, Character> diffMap = new HashMap<>();
diffMap.put('6', '9');
diffMap.put('9', '6');
diffMap.put('0', '0');
diffMap.put('1', '1');
diffMap.put('8', '8');
int result = 0;
for (int i = 0; i <= high.length() - low.length(); i++) {
result += countStrobo(low, high, 0, new char[low.length() + i], diffMap);
}
return result;
}
public int countStrobo(String low, String high, int curPos, char[] cache, Map<Character, Character> diffMap) {
int result = 0;
for (Map.Entry<Character, Character> entry : diffMap.entrySet()) {
int reverse = cache.length - curPos - 1;
char ch = entry.getKey();
char reversed = entry.getValue();
if (reverse == curPos && (ch == '6' || ch == '9')) continue;
cache[curPos] = ch;
cache[reverse] = reversed;
if (reverse - curPos > 1) {
if (curPos == 0 && ch == '0') continue;
result += countStrobo(low, high, curPos + 1, cache, diffMap);
} else {
if (curPos == 0 && ch == '0' && reverse != curPos) continue;
String candi = new String(cache);
boolean pass = true;
if (cache.length == low.length()) {
pass &= candi.compareTo(low) >= 0;
}
if (pass && cache.length == high.length()) {
pass &= candi.compareTo(high) <= 0;
}
result += pass ? 1 : 0;
}
}
return result;
}
事实上我们可以通过再加一点代码进行截肢操作,这样还可以省一半的时间,但有没有必要就见仁见智了。毕竟代码已经不短了
public int strobogrammaticInRange(String low, String high) {
if (low.length() > high.length() || (low.length() == high.length() && low.compareTo(high) > 0)) return 0;
Map<Character, Character> diffMap = new HashMap<>();
diffMap.put('6', '9');
diffMap.put('9', '6');
diffMap.put('0', '0');
diffMap.put('1', '1');
diffMap.put('8', '8');
int result = 0;
for (int i = 0; i <= high.length() - low.length(); i++) {
result += countStrobo(low, high, 0, new char[low.length() + i], diffMap, true, true);
}
return result;
}
public int countStrobo(String low, String high, int curPos, char[] cache, Map<Character, Character> diffMap, boolean lowEqual, boolean highEqual) {
int result = 0;
int reverse = cache.length - curPos - 1;
Character lowCh = curPos < low.length() ? low.charAt(curPos) : null;
Character highCh = high.charAt(curPos);
for (Map.Entry<Character, Character> entry : diffMap.entrySet()) {
char ch = entry.getKey();
char reversed = entry.getValue();
if (reverse == curPos && (ch == '6' || ch == '9')) continue;
cache[curPos] = ch;
cache[reverse] = reversed;
if (reverse - curPos > 1) {
if (curPos == 0 && ch == '0') continue;
if (lowEqual && lowCh != null) {
if (cache.length == low.length()) {
if (lowCh > ch) continue;
}
}
if (highEqual) {
if (cache.length == high.length()) {
if (highCh < ch) continue;
}
}
result += countStrobo(low, high, curPos + 1, cache, diffMap, lowEqual && lowCh == ch, highEqual && highCh == ch);
} else {
if (curPos == 0 && ch == '0' && reverse != curPos) continue;
String candi = new String(cache);
boolean pass = true;
if (cache.length == low.length()) {
pass &= candi.compareTo(low) >= 0;
}
if (pass && cache.length == high.length()) {
pass &= candi.compareTo(high) <= 0;
}
result += pass ? 1 : 0;
}
}
return result;
}