算法入门|位运算
位运算
基本的二进制运算法及其符号
运算 | 计算机符号 | 例子 |
---|---|---|
与 | & | 10&11=10 10&01=00 |
或 | | | 10|00=10 10|01=11 |
非 | ~ | ~10=01 |
异或 | ^ | 10^01=11 10^11=01 11^01=10 |
右移 | >> | a=10 a>>1 a=01 |
左移 | << | a=01 a<<1 a= 10 |
了解了计算机中位运算的相关计算规则即符号后,我们来看一下位运算再具体问题中的应用。
相关应用
【leetcode 231. 2的幂】
给你一个整数 n,请你判断该整数是否是 2 的幂次方。如果是,返回 true ;否则,返回 false 。
如果存在一个整数 x 使得 n == 2x ,则认为 n 是 2 的幂次方。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/power-of-two
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
分析:
最直观的以十进制分析,持续除2看除到1的过程中是否有商为奇数,若有则不是反之则是。
这种方式使用当然没有问题,但是位运算的方式提供了一种更加适合计算运算的更快的解决方案。
若一个数a是2的幂则必然有其二进制串仅有一个1,则其形式为1(n个0),否则为 (m-1个1)1(n个0)。
那么a-1 则必为0(n个1)或(m-1个1)0(n个1)
此时 若a为2的幂则必有a&(a-1)==0 反之则不等0;
class Solution {
public boolean isPowerOfTwo(int n) {
return n>0&&(n&(n-1))==0;
}
}
【leetcode 191. 位1的个数】
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为汉明重量)。
思路:求1的个数,联想上一题,是可以n&(n-1)后可以获得去掉n末位1之后的结果,重复这一过程直到n为0,循环次数即为1的个数。
class Solution {
public:
int hammingWeight(uint32_t n) {
int ret = 0;
while (n) {
n &= n - 1;
ret++;
}
return ret;
}
};
【leetcode 190. 颠倒二进制位】
颠倒给定的 32 位无符号整数的二进制位。
输入:n = 00000010100101000001111010011100
输出:964176192 (00111001011110000010100101000000)
解释:输入的二进制串 00000010100101000001111010011100 表示无符号整数 43261596,
因此返回 964176192,其二进制表示形式为 00111001011110000010100101000000。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/reverse-bits
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
想法:
类似栈的思想,将最低为先入栈即可。再位运算中实现可以将res每次右移1位,将n的最低位赋值给res,n左移一位,重复上述流程到n的位数次即可
class Solution {
public:
uint32_t reverseBits(uint32_t n) {
uint32_t ans=0;
//进制的本质
int i=32;
while(i--)
{
ans<<=1;
ans+=n&1;//获取最低位并加到ans上
n>>=1;
}
return ans;
}
};
【leetcode 136. 只出现一次的数字】
给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/single-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
想法:
第一想法是用hash,但是要求O(1)的空间复杂度,麻了,之间暴力可以实现空间复杂度的要求,但是时间太慢,后来在题解里发现有大佬给出了位运算的思路。
原理首先是 abb=a bab=a。由此由于数组中除了目标数字均有两个,那么直接将num中的数依次异或运算即可最后留下的即为出现一次的数字。
class Solution {
public int singleNumber(int[] nums) {
int ans=nums[0];
for(int i=1;i<nums.length;i++)
ans^=nums[i];
return ans;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具