找出1~10^n中数字翻转过来是本身的数( 96 ->96, 18 -> 81, 0 -> 0, 其他数字翻过来都不是数字)
设计一个函数,判断某个只包含数字的字符串是不是Ambigram(比如,69,88,609,818等都是Ambigram)。Follow up:给一个整数n,找出所有长为n的Ambigram。
可以先求出n-2的答案,再利用n-2的答案求出n的答案,这题方法比较绝,往n-2的答案里面append两个数字的时候分别各自加在两边就行,没必要往中间插入。
public boolean isAmbigram(String s) { int start = 0, end = s.length()-1; while(start <= end) { char left = s.charAt(start++); char right = s.charAt(end--); int val = Integer.parseInt(left+""+right); if(val!=0 && val!=11 && val!=88 && val!=69 && val!=96) { return false; } } return true; } public List<String> generateAmbigram(int n) { if(n == 1) { return Arrays.asList("0", "1", "8"); } else if(n == 2) { return Arrays.asList("00", "11", "88", "69", "96"); } List<String> result = new ArrayList<>(); List<String> list = generateAmbigram(n-2); for(String s:list) { result.add("0"+s+"0"); result.add("1"+s+"1"); result.add("8"+s+"8"); result.add("6"+s+"9"); result.add("9"+s+"6"); } return result; }
另外一种文法:找出所有长度小于等于N的Ambigram。用动态规划来解决。
public List<String> generateAmbigramDP(int n) { List<String> result = new ArrayList<>(); if(n <= 0) return result; List<String>[] dp = new List[n]; dp[0] = Arrays.asList("0", "1", "8"); if(n == 1) return dp[0]; dp[1] = Arrays.asList("00", "11", "88", "69", "96"); for(int i=2; i<n; i++) { List<String> list = dp[i-2]; dp[i] = new ArrayList<>(); for(String s:list) { dp[i].add("0"+s+"0"); dp[i].add("1"+s+"1"); dp[i].add("8"+s+"8"); dp[i].add("6"+s+"9"); dp[i].add("9"+s+"6"); } } for(List<String> list:dp) { result.addAll(list); } return result; }
再问:如果仅仅求有多少个长度为n的Ambigram呢?
【思路】
用动态规划来做。
if i is even, f[i] = f[i-1] + f[i-2] * 2
if i is odd, f[i] = f[i-1] * 3
// f[3] = f[2]*3 = 12;
// 101, 808, 609, 906
// 111, 818, 619, 916
// 181, 888, 689, 986
// f[4] = f[3] + f[2]*2 = 20
// - insert the same middle digit to every number in f[3]
// 1001, 8008, 6009, 9006
// 1111, 8118, 6119, 9116
// 1881, 8888, 6889, 9886
// - insert 69, 96 to every number in f[2]
// 1691, 8698, 6699, 9696
// 1961, 8968, 6969, 9966
public static int count180Number(int n) { // n is number of digits int[] f = new int[n+1]; f[1] = 3; // 0, 1, 8 f[2] = 4; // 11, 88, 69, 96 for(int i=3; i<=n; i++) { if(i % 2 == 0) { // i is even f[i] = f[i-1] + f[i-2] * 2; } else { f[i] = f[i-1] * 3; } } int cnt = 0; for(int num:f) { cnt += num; } return cnt; }