题目:数组中只有一个数出现了1次,其他的数都出现了k次,请输出只出现了1次的数。
思想:
把所有数转换为K进制的表示形式,然后再在每一位上做不进位加法,最后剩下孤独的数(再还原成十进制)
不进位加法:
3+3: | |||
(二进制) | 0 | 1 | 1 |
+ | 0 | 1 | 0 |
0 | 0 | 0 |
2个二进制做 不进位加法,结果得 0
10个十进制做 不进位加法,结果得0
则k个k进制数 不进位加法,结果为0
任意进制互转
1.手动取余法
2.Integer.toString(i,radix);
i传十进制 radix传需要进制
构造数组:建立字符的二位数组,存每位数字的三进制的每一位
int [] arr= {2,2,2,9,7,7,7,3,3,3,6,6,6,0,0,0};
int len=arr.length;//len:16
char[][] kRadix=new char[len][];
int k=3;
本来是这样的:
高位 | 低位 | |
2 | 2 | 1 |
2 | 1 | |
1 | 1 |
因为左边是高位,要补齐往右挪,才能把位对齐
翻转:这样低位就对齐了
低 | ||
1 | 2 | 2 |
1 | 2 | |
1 | 1 |
为了计算后面每一位要求和,maxlen记录多少次列的求和,
【进行转换】
int maxlen=0;
for(int i=0;i<len;i++) {
kRadix [i]=new StringBuilder(Integer.toString(arr[i],k)).reverse()
.toString().toCharArray();
//对于每个数字,先求得三进制的字符串 toString(arr[i],k),然后做一个反转(reverse),反转之后变成一个字符数组(CharArray)
//反转的目的:因为arr数组转化为三进制后位数可能不一样,反转过后的高位补0,这样高低位就对齐了,才能进行不进位加法
if(kRadix[i].length>maxlen) {
maxlen=kRadix[i].length;//三进制字符数组的长度大于了maxlen,做一下更新
}
}
【不进位加法】
int[] resArr =new int[maxlen];
for(int i=0;i<len;i++) {//遍历每一行,每一行是一个数字
for(int j=0;j<maxlen;j++) {//遍历每一列,每一列是这一位上 三进制的数值
///有的字符数组没有那么长,要做逻辑上的判断:有的三进制
if(j>=kRadix[i].length)//j大于等于了数组长度,每一位累加的时候就加0
resArr[j]+=0;
else //否则呢,就加上这一位数字和0间的差距,也就是从char转换为数字
resArr[j]+=(kRadix[i][j]-'0');//否则就加与0间的差距
}
}
得到每一位上加起来的和:
int res=0;
for(int i=0;i<maxlen;i++) {
res += (resArr[i]%k)*(int)(Math.pow(k, i));8%3=2
此2在第一位:就是2;若第二位:2x(3的一次方);第三位....
}
//把这个和取余,乘以 k的i次方
System.out.println(res);
public class a{
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;//len:16
char[][] kRadix=new char[len][];
int k=3;
//建立字符的二位数组,存每位数字的三进制
int maxlen=0;
//转成k进制字符数组
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)//j大于等于了数组长度,累加的时候就加0
resArr[j]+=0;
else
resArr[j]+=(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);
}
}
哈希表解法更简单:
此题仅仅练习用法,但是Intergar.toString转成任意形式字符串的用法会在别地用到
作业:
不用加减乘除,只用位运算完成的求和差乘商