一、找出数组中落单的那个数:
一个数组中,除了某一个数只出现了一次外,其他的数都出现了两次(只出现两次),请编写一个程序,不用辅助空间,遍历一次数组,找出这个数
思路:用到了相同数之间进行异或为0,不同数之间异或为1的结论,使所有数组中的数依次异或一次就好
public class Hello {
public static void main(String[] args) {
int arr [] = new int [11];
for(int i = 0;i<5;i++){
arr[i] = i;
arr[i+5] = i;
}
arr[10] = 6;//这个数是落单的,问怎么找出这个数
int a = arr[10];
for(int i = 0;i<10;i++){
a = a ^ arr[i];
}
System.out.println(a);
}
}
二、一个数的二进制有多少个1呢?
思路:
1.可以采用之前的移位操作,将32位都移1一次,来与1进行异或,结果为1即表示该位上是1,然后将这个数字统计下,即为1的个数
2.将一个数减一,则从右到左第一个为1的二进制位上的1为0,而右边的0会变成1,再与自己做&运算,就会使右边的二进制位上的数及当前位上的数全变为0,依次进行,直到该数字等于0,记下运算次数,即为1的个数
public class Hello {
public static void main(String[] args) {
//方法1
int count = 0;
int b = 335;//这个数的二进制有多少个1?
int i = 0;
for(i = 0;i<32;i++){
if(((b>>>i)&1) == 1){ //这是移位的操作
count++;
}
}
System.out.println(count);
//方法2
int count1 = 0;
while(b!= 0){
b = (b-1)&b; //用他减1根他自己取异或
count1++;
}
System.out.println(count1);
}
}
- 一个整数(不包括负数)若是二进制的整数次方,那他二进制位上至多只有一个1。
三、将整数的奇偶位互换:
思路:将一个整数与二进制表示为(1010 1010…)的数和(0101 0101…)的数分别进行与运算,然后前者左移一位,后者右移一位,再进行异或运算便可得到结果
public class Hello {
public static void main(String[] args) {
//将整数的奇偶位互换
int c = 6;
int a = 0xaaaaaaaa;//写成十六进制形式 这是1010 1010 ... 1010
int b = 0x55555555;//同理 这是0101 0101 ... 0101
c = ((c&a)>>1)^((c&b)<<1);
System.out.println(c);
}
}
四、0-1之间浮点实数的二进制表示
- 给定一个介于0-1之间的实数,如0.625,类型为double,打印他的二进制表示0.101,
- 因为小数点后的二进制分别表示0.5,0.25,0.125…
- 如果该数字无法精确地用32位以内的二进制表示则输出Error
思路:将这个数乘2,如果比1大,则该位上填1,然后将1减去,否则填0.
public class Hello {
public static void main(String[] args) {
double a = 0.625;
int count = 0;
double b;
String two = "0.";
while(count < 32){ //超过位数就跳出并打印ERROR
if((a * 2) >= 1){ //即是上述操作
a = a * 2 - 1;
two += "1";
}else {
a = a * 2;
two += "0";
}
if(a<=0){
break;
}
count++;
}
if(count<32){
System.out.println(two);
}else{
System.out.println("ERROR");
}
}
}
五、出现k次与出现一次
数组中只有一个数出现一次,其他的数都出现了k次,请输出出现一次的数:
思路
- k个相同的k进制数做不进位加法结果为0。
- 先把数都变成k进制的(下面以k=3举例)
- 再做不进位加法
- 再将数字转回来
public class Hello {
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][];//开辟二维数组存储3进制的形式
int k = 3;//设定为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)
resArr[j] += 0;//如果长了,那就加0啦
else {
resArr[j] += (kRadix[i][j] - '0'); //从char转换成数字
}
}
}
int res = 0;
for(int i = 0;i<maxlen;i++){
res += (resArr[i] % k) * (int)(Math.pow(k,i));//3的多少次
}
System.out.println(res);
}
}