//c中右移操作符>>,对于有符号数,右移时,符号位不变,左边补符号位,对于无符号数,右移时,左边补0 //例如8>>31,则是11111111111111111111,实际值为-1,并不会只剩下符号位1 intflip(int n) { return n ^ 1; // 必须保证n一定是0或者1,0变1,1变0 } // 非负数返回1负数返回0 intsign(int n) { return !((n >> 31)&1); // n >> 31, 右移31位,使符号位移动到0位置 } // 有溢出风险的实现,c可能超出整数范围 intgetMax1(int a, int b) { int c1 = a - b; int returnA = sign(c1); // 非负数返回1负数返回0 int returnB = flip(returnA); // 非负数返回0负数返回1, 与returnA相反 return a * returnA + b * returnB; } // 没有任何问题的实现 // 不会溢出分析:溢出后c的正负可能会发生改变,因此我们判断大小时的条件只用c不会溢出的情况下判断,无法确定是否溢出时不用c进行判断 // 即ab符号不同,c不会溢出,ab符号相同,c可能溢出,索引在判断returnA时只有sameAB时才会用c进行判断 intgetMax2(int a, int b) { int c = a - b; int sa = sign(a); int sb = sign(b); int sc = sign(c); int diffAB = sa ^ sb; // 判断ab符号是否相同。不同为1,相同为0 int sameAB = flip(diffAB); // 不同为0,相同为1 int returnA = diffAB * sa + sameAB * sc; // a>b的条件为 ab相同c为非负,ab不同a为非负。 int returnB = flip(returnA); return a * returnA + b * returnB; }
publicstaticintfind(int[] arr, int m){ int[] cnts = newint[32]; for (int num : arr){ for (inti=0; i < 32; i++){ cnts[i] +=(num >> i) & 1; } } intans=0; for (inti=0; i < 32; i++){ if (cnts[i] % m != 0){ ans ^= 1 << i; } } return ans; }
publicstaticfinalintnear2power(int n){ if (n == 0) { return1; } n--; n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;//这里是32位系统,如果是64位系统,就是直到n |= n >>> 32;该实现的是将最左边的1后面的所有位都置为1 return n + 1; }
区间[left,right]内所有数字&的结果
有零出零right与right-1做&,相当于最右侧的1无法保留
1 2 3 4 5 6
publicstaticintrangeBitwiseAnd(int left, int right){ while(left < right){ right -= right & -right;//right减去只有最右侧的1的数,Kernighan算法 } return right; }