①颠倒二进制位
颠倒给定的 32 位无符号整数的二进制位。
示例:
输入: 43261596 输出: 964176192 解释: 43261596 的二进制表示形式为 00000010100101000001111010011100 , 返回 964176192,其二进制表示形式为 00111001011110000010100101000000 。
进阶:
如果多次调用这个函数,你将如何优化你的算法?
1.本蒻的简单直接的写法,将二进制位存储到容器中,然后翻转进行求和:
class Solution {
public:
uint32_t reverseBits(uint32_t n) {
vector<int> vec; //存储二进制位
int cnt = 0;
while (n > 0)
{
vec.push_back(n % 2);
n /= 2;
cnt++;
}
while (cnt < 32)
{
vec.push_back(0);
cnt++;
}
reverse(vec.begin(), vec.end()); //翻转
uint32_t sum = 0;
for (int i = 0; i < 32; ++i)
{
if (vec[i] == 1)
{
sum += pow(2, i); //求和
}
}
return sum;
}
};
2.从右向左遍历二进制位,如果当前二进制位为1,则结果res左移并加1,否则左移,将当前二进制位右移,依次遍历得到结果:
具体分析:
输入数n:20 则二进制位表示:10100
进行遍历:n从低位开始遍历,即从0到1
第一位:0 res:0
第二位:0 res:0
第三位:1 res:此时左移加1,为1
第四位:0 res:1
第五位:1 res:左移加1得到结果为5
class Solution {
public:
uint32_t reverseBits(uint32_t n) {
uint32_t res = 0;
for (int i = 0;i < 32; ++i)
{
if (n & 1 == 1) //n的最低位为1,则结果res左移并加1
res = (res<<1) + 1;
else //否则结果res左移
res = res << 1;
n = n >> 1; //取n的下一位
}
return res;
}
};
3.直接将n右移i位,通过‘&’1取出该位,加到左移1位后的res即得结果(实质与上述思路一致):
class Solution {
public:
uint32_t reverseBits(uint32_t n) {
uint32_t res = 0;
for (int i = 0; i < 32; ++i) {
res = (res << 1) + (n >> i & 1); //将n右移i位,然后与1取出该位加到结果中
}
return res;
}
};
4.将n右移i位,通过与1取出该位,然后将其左移(31-i)位,然后与结果res进行或运算,即可得到结果:
class Solution {
public:
uint32_t reverseBits(uint32_t n) {
uint32_t res = 0;
for (int i = 0; i < 32; ++i) {
res |= ((n >> i) & 1) << (31 - i); //n右移i位与1取出该位,左移31-i位得到翻转位,然后与结果res或运算
}
return res;
}
};
②位1的个数
编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。
示例 :
输入: 11
输出: 3
解释: 整数 11 的二进制表示为 00000000000000000000000000001011
示例 2:
输入: 128 输出: 1 解释: 整数 128 的二进制表示为 00000000000000000000000010000000
1.此题与上题类似,会做一道就会另一道,也是n右移i位与1取出该位和1判断,如果相等则计数加1:
class Solution {
public:
int hammingWeight(uint32_t n) {
int cnt = 0;
for (int i = 0; i < 32; ++i)
{
if ((n >> i) & 1 == 1) //n右移i位与1取出该位,和1判断
++cnt;
}
return cnt;
}
};