低质量解答,大佬们轻点拷打,,(感觉要被盒了
1.implication
* implication - given input x and y, which are binary
* (taking the values 0 or 1), return x -> y in propositional logic -
* 0 for false, 1 for true
*
* Below is a truth table for x -> y where A is the result
*
* |-----------|-----|
* | x | y | A |
* |-----------|-----|
* | 1 | 1 | 1 |
* |-----------|-----|
* | 1 | 0 | 0 |
* |-----------|-----|
* | 0 | 1 | 1 |
* |-----------|-----|
* | 0 | 0 | 1 |
* |-----------|-----|
*
*
* Example: implication(1L,1L) = 1L
* implication(1L,0L) = 0L
* Rating: 2
*/
用位运算硬凑,经过几次尝试之后可得答案
long implication(long x, long y) {
return (((!x) ^ y) | y);
}
2.leastBitPos
/*
* leastBitPos - return a mask that marks the position of the
* least significant 1 bit. If x == 0, return 0
* Example: leastBitPos(96L) = 0x20L
* Rating: 2
*/
long leastBitPos(long x) {
return x & (-x);
}
/*
lowbit操作
3.distinctNegation
/*
* distinctNegation - returns 1 if x != -x.
* and 0 otherwise
* Rating: 2
*/
long distinctNegation(long x) {
// only 0 and tmin
return !((!x) | !(~(x ^ (x - 1))));
}
如果x不等于-x就返回1。
在数学认识下只有0=-0,但是在二进制补码表示中,tmin=0x8000000000000000。
-tmin为tmin除符号位以外取反+1,仍等于tmin。
因此,如果x==0||x==tmin就返回1。判断x是0,可以用!运算。
判断x是tmin,则需要运用tmin的性质。tmin-1由于溢出是tmax,tmin^tmax==-1,-1取反为0。
(应该没有别的数还满足这个性质8,没细想
4.fitsBits
/*
* fitsBits - return 1 if x can be represented as an
* n-bit, two's complement integer.
* 1 <= n <= 64
* Examples: fitsBits(5,3) = 0L, fitsBits(-4,3) = 1L
* Rating: 2
*/
long fitsBits(long x, long n) {
x >>= (n - 1);
return (!x) | !(x + 1);
}
一个数如果可以被表达为n—bits。则这个数右移n-1位后,正数为0,负数全是1,即-1。
5.trueFiveEighths
/*
* trueFiveEighths - multiplies by 5/8 rounding toward 0,
* avoiding errors due to overflow
* Examples:
* trueFiveEighths(11L) = 6L
* trueFiveEighths(-9L) = -5L
* trueFiveEighths(0x3000000000000000L) = 0x1E00000000000000L (no overflow)
* Rating: 4
*/
long trueFiveEighths(long x) {
long b = x & 7;
long backup = x;
x >>= 3;
// negative number << will [] if b!=0
return ((x << 2) + x) + (((b << 2) + b) >> 3) +
((!!b) & (!!(backup >> 63)));
}
一个数除以8向下取整等价于右移3位。一个数乘以5等价于乘(101)b,即x=x<<2+x。
最简单思路:先乘5再除以8,显然会溢出。
也就是必须先除以8。这里特别注意除以8之后,x/8的余数直接被舍去了。这个余数最大是7,7乘以5除以8向下取整等于4,不等于0。也就是说答案还要加上余数的影响:
然后开开心心的btest。结果报错,发现输入tmin时,结果等于答案-1。再读题,发现需要向0取整,也就是说当x是负数的时候需要向上取整,而不是向下取整。
没想到什么别的好方法,直接使x是负数且模8不为0时,答案+1。
6.addOK
/*
* addOK - Determine if can compute x+y without overflow
* Example: addOK(0x8000000000000000L,0x8000000000000000L) = 0L,
* addOK(0x8000000000000000L,0x7000000000000000L) = 1L,
* Rating: 3
*/
long addOK(long x, long y) {
long a = (x >> 63) & 1;
long b = (y >> 63) & 1;
long res = x + y;
long c = (res >> 63) & 1;
return (a ^ b) | (!(c ^ a));
}
异号相加不会溢出。
同号相加可能溢出,溢出时结果数和x,y符号不同。
7.isPower2
/*
* isPower2 - returns 1 if x is a power of 2, and 0 otherwise
* Examples: isPower2(5L) = 0L, isPower2(8L) = 1L, isPower2(0) = 0L
* Note that no negative number is a power of 2.
* Rating: 3
*/
long isPower2(long x) {
// x-x&(-x)==0 and x != tmin
long lowbit = x & (-x);
int sign = (x >> 63) & 1;
return (!!x) & (!(x - lowbit)) & (!sign);
}
判断x是否是2的n次幂。n为1~64
注意负数不会是2的n次幂。
如果是,则x的二进制表示只有一个1,因此x==lowbit(x)。但是tmin也满足这个条件,因此再排除掉所有负数即可。
8.rotateLeft
/*
* rotateLeft - Rotate x to the left by n
* Can assume that 0 <= n <= 63
* Examples:
* rotateLeft(0x8765432187654321L,4L) = 0x7654321876543218L
* Rating: 3
*/
long rotateLeft(long x, long n) {
long a = (x >> (64 - n)) & ((1l << n) - 1);
x = (x << n) + a;
return x;
}
题意分析:x左移n位,原来左边的n位放到右边。
被移走的 直接 ‘’与 ‘’左移出的那一堆0就行
9.isPalindrome
/*
* isPalindrome - Return 1 if bit pattern in x is equal to its mirror image
* Example: isPalindrome(0x6F0F0123c480F0F6L) = 1L
* Rating: 4
*/
long isPalindrome(long x) {
// divide-and-conquer strategy
long a1 = 0xaaaaaaaaaaaaaaaa;
long a2 = 0xcccccccccccccccc;
long a3 = 0xf0f0f0f0f0f0f0f0;
long a4 = 0xff00ff00ff00ff00;
long a5 = 0xffff0000ffff0000;
long a6 = 0xffffffff00000000;
long backup = x;
x = ((x << 32) & a6) | ((x >> 32) & (~a6));
x = ((x << 16) & a5) | ((x >> 16) & (~a5));
x = ((x << 8) & a4) | ((x >> 8) & (~a4));
x = ((x << 4) & a3) | ((x >> 4) & (~a3));
x = ((x << 2) & a2) | ((x >> 2) & (~a2));
x = ((x << 1) & a1) | ((x >> 1) & (~a1));
return !(backup ^ x);
}
题意:判断x在2的补码表示下是否是一个回文数(包括前导0)
判断回文数,我个人已知的方法只有倒着扣出所有数,与原数比较。
一个个扣不现实,因此我个人考虑分治策略能不能成功:要把原数倒着扣出来,可以通过以下步骤:
- 把前32位和后32位交换,然后把两部分分别倒过来
- 把1~16位和17~32位交换,然后分别倒过来。把33~48位和49~64交换,然后分别倒过来
- .......
- 把奇数位和偶数位交换
发现分治策略可行,接下来考虑怎么交换。直觉告诉我们会用到左移右移运算。
做第一步,假设这个数是xxxxyyyy,我们可能会考虑变成xxxx0000+0000yyyy(也可能是1111yyyy)。接下来思考怎么整出这两个数即可。盯这这个数本身做位运算得到这两个数,个人觉得很难,因此被迫借助11110000来帮助我们。xxxx0000&11110000=xxxx0000。
1111yyyy&(00001111)=0000yyyy,发现00001111实际上就是11110000的反。因此定义1个这样的数就行。
第一步解决了,剩下几步同理
10.bitParity
/*
* bitParity - returns 1 if x contains an odd number of 0's
* Examples: bitParity(5L) = 0L, bitParity(7L) = 1L
* Rating: 4
*/
long bitParity(long x) {
// Add all 1 to the first bit without considering the rounding
// So it can use ' ^ '
x = (x >> 32) ^ x;
x = (x >> 16) ^ x;
x = (x >> 8) ^ x;
x = (x >> 4) ^ x;
x = (x >> 2) ^ x;
x = (x >> 1) ^ x;
x = (x & 1);
return x;
}
判断x的二进制表示是否有奇数个0。异或不改变奇偶性。
11.absVal
/*
* absVal - absolute value of x
* Example: absVal(-1) = 1.
* You may assume -TMax <= x <= TMax
* Rating: 4
*/
long absVal(long x) {
long sign = !!(x >> 63);
return (x ^ (-sign)) + sign;
}
-x=~x+1。呃呃呃判断一下符号位就完事了,不知道为什么这道题4分。
个人做题时发现的小tips
-1=11111111
tmin=10000000
tmax=01111111
only !0=1
>> //表示除以2的几次方 下取整 对正负数通用
sign=(x>>63)&1
-x=~x+1
//负数原码求补码 非符号位取反 +1 ,补码求原码同样
//因为对位运算还是不熟练,还有好多tips忘了 无所谓,我会开摆