Google Interview - 数字旋转180度

找出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;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值