题目一
一个数组里除了某-一个数字之外,其他的数字都出现了两次。请写程序找出这个只出现一次的数字。
暴力思路:使用Map记录数字出现的数量,最后找出出现一次的。
巧妙思路:使用异或符号(^),异或符号为不进位加法,两个相同的数字异或为0,所以可以利用这个性质将所有数字异或一遍,最终的就是答案答案。
public static void main(String[] args) {
int nums[] = {1,1,2,2,3,4,5,3,4};
System.out.println(Arrays.toString(nums));
int res = 0;
for (int i = 0; i <nums.length ; i++) {
res = res^nums[i];
}
System.out.println(res);
}
题目二
1- 1000这1000个数放在含有1001个元素的数组中,只有唯一的一一个元素值重复,其它均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现?
暴力思路:使用Map记录数字出现的数量,最后找出出现两次的。
巧妙思路:和第一题类似,使用异或符号(^),异或符号为不进位加法,两个相同的数字异或为0,所以可以利用这个性质来寻求答案。
public static void main(String[] args) {
int size = 5;
int nums[] = new int[size+1];
for(int i=0;i<size;i++){
nums[i]=i+1;
}
nums[size]=(int)(Math.random()*size);
System.out.println(Arrays.toString(nums));
int tmp = 0;
// 先对 tmp 从 1-size 做一下异或操作
for (int i = 1; i <= size; i++) {
tmp = tmp^i;
}
// 在对每一个数进行异或,相同的数字将变为,最终剩下的数字为答案
for (int i = 0; i <= size ; i++) {
tmp = tmp^nums[i];
}
System.out.println(tmp);
}
题目三
请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。
例: 9的二进制表示为1001,有2位是1
暴力思路:将数字转换为二进制,通过遍历的方式统计1的数量。
public static void main(String[] args) {
int n = 9;
String s = Integer.toBinaryString(n);
System.out.println(s);
char[] chars = s.toCharArray();
int count=0;
for (int i = 0; i < chars.length; i++) {
if(chars[i]=='1'){
count++;
}
}
System.out.println(count);
}
巧妙思路:可以借助左移(<<)符号来快速统计,左移每次移动一次二进制数,末尾补0,如果 int 类型数据可以通过移动 32 次来获取答案。
public static void main(String[] args) {
int n = 9;
String s = Integer.toBinaryString(n);
System.out.println(s);
int count = 0;
for (int i = 1; i <= 32 ; i++) {
if((n&(1<<i)) == (1<<i)){
count++;
}
}
System.out.println(count);
}
题目四
判断一个数是不是 2 的整数次方
暴力思路:每次除2,判断位数是否是整数。
巧妙思路:将一个数与这个数减一进行与运算,判断得到的结果是否为0既可知道其是否为整数。
例如:8(1000)^7(0111)=0
public static void main(String[] args) {
int n1 = 8;
int n2 = 9;
System.out.println((n1&(n1-1))==0);
System.out.println((n2&(n2-1))==0);
}
题目五
将整数的二进制奇偶位进行交换
暴力思路:将数字转换为二进制,然后做两两交换操作。
巧妙思路:将原数字与(010101…01)进行与运算,得到a;在将原数组与(1010…10)进行与运算,得到b;然后将a左移一位和b右移一位进行异或操作,最终得到的数字就为结果了。
public static void main(String[] args) {
int n = 6;
int a = n&0x55555555;//0101....01
int b = n&0xaaaaaaaa;//1010....10
System.out.println((a<<1)^(b>>1));
}