一道笔试题
本文由tom原创,转载请注明原文链接:https://work-jlsun.github.io//2016/02/22/code.html
题目:过年了,考拉哥哥搞了一批礼品券出售。每张礼品券上有个涂层,用户刮开涂层后,将涂层背后的16位卡密输入到考拉就可以兑换相应的券。在印刷礼品券的时候,印刷出来后我们才发现印刷的g和9长的一摸一样。此时,后台数据库由于对卡密做了三次加密无法破解,卖出去的礼品券无法收回。为了保证礼品卡能正常使用,我们的解决方案如下,即对所有的g和数字9进行模糊匹配(已验证该方案下当前批次的礼品券卡密不会出现重复)。现在要求,用户输入一串十六位的卡密,找出所有相似的卡密。即如果用户输入是99xxx,则卡密ggxxx,g9xxx,9gxxx,99xxx都应匹配。
解题思路: 忽略其他客观因素,此题基本就是求所有g和9位置替换成9或g的排列组合,举例9gxx,如图一所示,所有可能组合为如下二叉树的路径组合(向左走为9,向右走为g,二叉树深度即为9和g
的数目),所以此题基本抽象为二叉树的遍历。最优解为通过使用位运算(如图2所示,假设9等同于0,g等同于1,那么所有组合为0到3的所有二进制表示);普通解法为递归。
//java code
public static String[] getSimilarVoucher(char[] code){
Integer len = code.length;
Integer similarNum = 0;
Integer[] indexString = new Integer[len];
for (Integer i = 0; i< len;i++) {
if (code[i] == '9' || code[i] == 'g'){
indexString[similarNum] = i;
similarNum++;
}
}
Integer n = 1 << similarNum;
String[] similarSet = new String[n];
for ( Integer i = 0; i < n; i++) {
char[] similarCode = code;
for (Integer j = 0; j < similarNum; j++ ){
if ((i & (1 << j)) == 0) {
similarCode[indexString[j]] = '9';
}else {
similarCode[indexString[j]] = 'g';
}
}
similarSet[i] = String.valueOf(similarCode);
}
for (Integer i = 0; i < similarSet.length; i++){
System.out.println(similarSet[i]);
}
return similarSet;
}
This article used CC-BY-SA-4.0 license, please follow it.