位运算的简单知识
位运算中,需要记住的几个点为:
- 想要去最后一位,用
num % 2
. - 要去除最后一位,则用
num = num / 2
- 如果判断一个数是2的幂次方,用
(n & -n) == n
,下面会详细说明 - 两个相同的数异或为0,全部位与0 异或 值不变,全部位与1 异或 相当于取反.
手算求补小技巧::
从最后一位开始,寻找到第一个1,然后1前面的位全部取反即可完成求补!
231. 2 的幂
题意:
给你一个整数 n,请你判断该整数是否是 2 的幂次方。如果是,返回 true ;否则,返回 false 。
如果存在一个整数 x 使得 n == 2x ,则认为 n 是 2 的幂次方。
示例 1:
输入:n = 1
输出:true
解释:20 = 1
示例 2:
输入:n = 16
输出:true
解释:24 = 16
示例 3:
输入:n = 3
输出:false
解题思路
问 答 怎么判断一个数是否为2的幂? 只需要判断整个数就只有一个1. 怎么判断只有一个1? 我们只需要对整个数先取补码,则原码取反+1.与运算,如果得到原本相同的数就说明是一个数,如果不是就证明不止一个.
举个例子
例一:::4的原码是:
0000 0100
. 那么它的补码为:1111 1100
这时候做与运算结果为:0000 0100
等于原来的数.例二:::5的原码为:
0000 0101
.那么它的补码为:1111 1011
这时候做与运算结果为:0000 0001
不等于原来的数.你可以列举其它的例子,当且仅当只有一个1时,与的结果才会等于原来的数字.
代码:
class Solution {
public:
bool isPowerOfTwo(int n) {
if(n <= 0)
return false;
return (n & -n) == n;
}
};
191. 位1的个数
题意
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。
示例 1:
输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。
示例 2:
输入:00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'。
示例 3:
输入:11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'。
解题思路:
只需要每次都取出最后一位来判断是否为1即可,直到 n等于0结束;
代码:
class Solution {
public:
int hammingWeight(uint32_t n) {
int res = 0;
while (n)
{
res += n % 2;
n = n / 2;
}
return res;
}
};
190. 颠倒二进制位
题意:
颠倒给定的 32 位无符号整数的二进制位。
示例 1:
输入: 00000010100101000001111010011100
输出: 00111001011110000010100101000000
解释: 输入的二进制串 00000010100101000001111010011100 表示无符号整数 43261596,
因此返回 964176192,其二进制表示形式为 00111001011110000010100101000000。
示例 2:
输入:11111111111111111111111111111101
输出:10111111111111111111111111111111
解释:输入的二进制串 11111111111111111111111111111101 表示无符号整数 4294967293,
因此返回 3221225471 其二进制表示形式为 10111111111111111111111111111111 。
示例 1:
输入:n = 00000010100101000001111010011100
输出:964176192 (00111001011110000010100101000000)
解释:输入的二进制串 00000010100101000001111010011100 表示无符号整数 43261596,
因此返回 964176192,其二进制表示形式为 00111001011110000010100101000000。
解题思路:
定义一个变量,只需要每次变量左移一位或上
n
的最后一位,然后n右移一位.直到n等于0为止.判断移动次数,然后添加移动够32次即可.
代码:
class Solution {
public:
uint32_t reverseBits(uint32_t n) {
if(n == 0)
return 0;
int ans = 0;
int num = 0; //记录移动多少次
while (n)
{
ans = ans << 1 | (n % 2);
n = n / 2;
num++;
}
ans = ans << (32 - num); //需要移动够32次
return ans;
}
};
136. 只出现一次的数字
题意:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
解题思路:
出去全部数字,逐个异或,遇到相同的就会消除,最后只会剩下一个不同的.
代码
class Solution {
public:
int singleNumber(vector<int>& nums) {
int res = 0;
for (const int i : nums)
{
res ^= i;
}
return res;
}
};
总结:
位运算在某些题运用会有奇效,所以需要掌握一点简单知识.