算法入门|位运算

位运算

基本的二进制运算法及其符号

运算 计算机符号 例子
& 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;
    }
}

posted @   比奇堡的黄色小海绵  阅读(71)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示