《算法很美》一、位运算与进制基础(笔记)
1.相关基础
位运算
- 在处理整形数值时,可以直接对组成整形数值的各个位进行操作。
- &(与),|(或),^(异或),~(非/取反)
- (>>和<<)运算符将二进制位进行右移或左移操作
- (>>>)运算符将用0填充高位;(>>)运算符用符号位填充高位,没有(<<<)运算符
- 对于int型,1<<35与1<<3是相同的,而左边的操作数是long型时需要对右侧操作数模64
2. 例题
判断奇偶数
-
把数字&1;
-
奇数是1,所以运算结果为1
-
偶数是0,所以运算结果为0
int x=1; while (x<5){ int b=x&1; if (b==1){ System.out.println(x+":为奇数"); }else { System.out.println(x+":为偶数"); } x++; }
找出唯一成对的数:
例题:1-1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素值重复,其他均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现?
- 用异或实现
/**
*找出唯一成对的数
*1.数组插入数据
*2.定义一个x和1-10异或
*3.x和arr异或。原先不重复的数就会被异或掉啦。
*/
int N=11;
int[]arr=new int[N];
//定义包含一组重复数的arr数列
arr[arr.length-1]=(int)(Math.random()*N-1)+1;
int index=(int)(Math.random()*N);
int t=0;
t=arr[index];
arr[index]=arr[arr.length-1];
arr[arr.length-1]=t;
//先输出数组,便于观察
System.out.println(Arrays.toString(arr));
//定义一个x,让它先和1-10异或即(x=(x^1^2^3^4^5^6^7^8^9^10))
int x=0;
for (int i = 1; i < arr.length; i++) {
x=(x^i);
}
//再让x和arr数组异或,这样相同的数就消去了。
//x=(x^1^2^3^4^5^6^7^8^9^10)
//x^arr后,原先重复的数字就有3个了,就不会被消去啦。
for (int i = 0; i < arr.length; i++) {
x=x^arr[i];
}
System.out.println(x);
- 计数下标,辅助空间
int N=11;
int[]arr=new int[N];
for (int i = 0; i < arr.length; i++) {
arr[i]=i+1;
}
arr[arr.length-1]=(int)(Math.random()*N-1)+1;
int index=(int)(Math.random()*N);
int t=0;
t=arr[index];
arr[index]=arr[arr.length-1];
arr[arr.length-1]=t;
//以上为创建数组
int []helper=new int [N];
for (int i = 0; i < arr.length; i++) {
//helper数组的下标记录arr数组中的每一个数,helper对应下标的每个值为arr数组里数出现的次数。
helper[arr[i]]++;
}
for (int i = 0; i < helper.length; i++) {
if (helper[i]==2) {
System.out.println(i);
}
}
找出落单的那个数:
int N=11;
int[]arr=new int[N];
for (int i = 0; i <arr.length; i++) {
arr[i]=i+1;
if (i>=5) {
arr[i]=i-4;
}
}
arr[arr.length-1]=(int)(Math.random()*N-1)+6;
int index=(int)(Math.random()*N);
int t=0;
t=arr[index];
arr[index]=arr[arr.length-1];
arr[arr.length-1]=t;
System.out.println(Arrays.toString(arr));