题目:数组中arr只有一个数出现了1次,其他的数都出现了k次,请输出这个只出现了一次的数。
思路:这道题目要求使用位运算实现,如果采用数据结构Map就会简单很多。解此题前先了解不进位加法的思想,比如两个二进制数10+10 进行不进位加法得到的结果是00(二进制),再比如10个51进行不进位加法结果也为00(十进制),这里就可以得出结论,如果K个相同的K进制数进行无进位加法,相加的结果一定是每一位上都为0的K进制数。那么这道题的思路就是,构造一个二位数组kRadix,其中一维索引是数组arr的长度,二位索引存的就是每个数字的三进制字符串再反转过后的字符数组,这里要反转的目的是因为数组arr转化成三进制数组时的长度不一样,反转过后的字符串高位补0,这样高低位就对齐了,这样才能进行不进位加法。然后对每一列采用不进位加法,将结果存进一个一维数组resArr,再然后遍历这个数组分别对K求余累加算出十进制,得出的数据就是唯一的那个数。
代码:
public class 出现K次 { public static void main(String[] args) {
int []arr = {2,2,2,9,7,7,7,3,3,3,6,6,6,0,0,0};
int len = arr.length;
char [][] kRadix = new char[len][];
int k = 3;
// 转成k进制字符数组
int maxLen = 0;
// 对于每个数字
for (int i = 0; i < len; i++) {
// 求每个数字的三进制字符串并反转,然后转为字符数组
kRadix[i] = new StringBuilder(Integer.toString(arr[i],k)).reverse().toString().toCharArray();
if (kRadix[i].length>maxLen) {
maxLen = kRadix[i].length;
}
}
int [] resArr = new int[maxLen];
// 不进位加法
for (int i = 0; i < len; i++) {
// 不进位加法
for (int j = 0; j < maxLen; j++) {
if (j>=kRadix[i].length) {
resArr[j] += 0;
}else {
resArr[j] += (kRadix[i][j]-'0'); // kRadix[i][j]-'0' 字符-'0' 从字符转换成了数字
}
}
}
int res = 0;
for (int i = 0; i < maxLen; i++) {
res += (resArr[i] % k ) * (int)(Math.pow(k, i)); // 累加求出十进制
}
System.out.println("数组中唯一出现的数字是:"+res); } }
结果: