算法 | 位运算(哈希思想)

位运算

|----------|----|----------------------------|
| & | 与 | 两个位都为1时,结果才为1**(有0为0)** |
| | | 或 | 两个位都为0时,结果才为0**(有1为1)** |
| ^ | 异或 | 两个位相同为0,相异为1 |
| ~ | 取反 | 0变1,1变0 |
| << | 左移 | 各二进位全部左移若干位,高位丢弃,低位补0 |
| >> | 右移 | 各二进位全部右移若干位,高位补0或符号位补齐 |

判定字符是否唯一

面试题 01.01. 判定字符是否唯一 - 力扣(LeetCode)https://leetcode.cn/problems/is-unique-lcci/description/

题解:

由于题目限制我们不能使用额外的数据结构,我们用位图来解决,位图的原理和哈希表类似。

int i=ch-'a' 来记录字母对应的位图的下标,

  • 如果该下标在位图中为 1,即 bitmap&(1<<i) == 1 ,说明该字母在字符串中不唯一
  • 如果该下标在位图中为 0,则该字母在字符串中是唯一的!则把该位置从 0 改为 1.
cpp 复制代码
class Solution {
public:
    bool isUnique(string astr) {
        if(astr.size()>26) return false;

        int bitmap=0;
        for(auto ch:astr)
        {
            int i=ch-'a';
            if(bitmap&(1<<i)) return false;

            bitmap|=(1<<i);
        }
        return true;
    }
};

丢失的数字

268. 丢失的数字 - 力扣(LeetCode)https://leetcode.cn/problems/missing-number/description/

题解:

异或 -- 相同为0,不同为1

即 1 ^ 1 = 0、0 ^ 0 = 0、1 ^ 0 = 1

由运算规则可知,任何二进制数与零异或,都会等于其本身,即 A ^ 0 = A。


异或性质

(1)交换律: A ^ B = B ^ A

(2)结合律: ( A ^ B ) ^ C = A ^ ( B ^ C )

(3)自反性: A ^ B ^ B = A (由结合律可推: A ^ B ^ B = A ^ ( B ^ B ) = A ^ 0 = A)
因为缺失的数字在这两个数组中只出现了1次,而其余数字都出现了2次,出现2次的数字异或后结果为0。

只要把完整的数组和缺失的数组异或在一起,就可以找到缺失的数字!

cpp 复制代码
class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int n=nums.size();
        int ret=0;
        for(auto x:nums) ret^=x;
        for(int i=0;i<=n;i++) ret^=i;
        return ret;
    }
};

两整数之和

371. 两整数之和 - 力扣(LeetCode)https://leetcode.cn/problems/sum-of-two-integers/description/

题解:

由于不能直接使用加法,只能使用位运算。


把两个数都化为二进制进行相加,二进制相加时,1+1=10,0+0=0,1+0=1,和异或的规则类似,但需要处理进位。

如果两个数都是 1 才需要进位,有一个数不是 1 就不需要进位,这符合 & 的规则。因为进位是向前进 1 位,所以 & 后的结果需要左移 1 位。

把 ^ 和 & 的结果相加起来就可以得到进位后的结果,但是本道题不能使用加法,所以再次 ^ 和 & ,来模拟加法,直到 & 得到的结果为 0,也就是不需要进位时,就可以得到最终结果

cpp 复制代码
class Solution {
public:
    int getSum(int a, int b) {
        while(b!=0)
        {
            int x=(a^b);
            int carry =(a&b)<<1;
            a=x;
            b=carry;
        }
        return a;
    }
};

只出现一次的数字 II

137. 只出现一次的数字 II - 力扣(LeetCode)https://leetcode.cn/problems/single-number-ii/description/

题解:

把数组中所有的数相加,对相加得到的和的某一位数字,有如下 4 种情况:3个0 + 0、3个0 + 1、3个1 + 0、3个1 + 1,把这 4 种情况都模3,就可以得到 0、1、0、1,即只出现一次的数字的对应的二进制。

cpp 复制代码
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ret=0;
        for(int i=0;i<32;i++)
        {
            int sum=0;
            for(auto x:nums)
            {
                if((x>>i)&1 == 1) ++sum;
            }
            sum%=3;
            if(sum==1)
                ret |=(sum<<i);
        }
        return ret;
    }
};

消失的两个数字

面试题 17.19. 消失的两个数字 - 力扣(LeetCode)

题解:

这道题类似丢失的数字,只是丢失的是两个数字。

把缺失数字的数组和完整数字的数组异或在一起,除了 a、b只出现了一次,其余数字出现了两次,所以异或的结果其实就是 a^b由于 a、b 是不同的数字,即异或的结果中肯定有某一位的数字为1。

我们找出这一位 x(如果有多位的话,找出其中一位即可),就可以把数组的数字分为两类,一类是 x 位上的二进制为 1,一类是 x 位上的二进制为 0,假设 a 的 x 位上的二进制为 0 ,b 的 x 位上的二进制为 1。

对于 x 位上的二进制为 1 的缺失数字的数组和完整数字的数组,a 只出现一次,其余数字都出现 2次,对于 x 位上的二进制为 0 的 b 也是同理,问题就转换为求一个丢失的数字。

cpp 复制代码
class Solution {
public:
    vector<int> missingTwo(vector<int>& nums) {
        //把所有的数异或在一起
        int tmp=0;
        for(auto x:nums) tmp^=x;
        for(int i=1;i<=nums.size()+2;i++)   tmp^=i;
        //找出a、b中比特位不同的那一位
        int diff=0;
        while(1)
        {
            if(((tmp>>diff) & 1) == 1) break;
            else diff++;
        }
        //根据 diff位的不同,将所有的数划分为两类来异或
        int a=0,b=0;
        for(auto x:nums)
        {
            if(((x>>diff) & 1) ==1) b^=x;
            else a^=x;
        }
        for(int i=1;i<=nums.size()+2;i++)
        {
            if(((i>>diff) & 1) ==1) b^=i;
            else a^=i;
        }
        return {a,b};
    }
};
相关推荐
hsling松子15 分钟前
使用PaddleHub智能生成,献上浓情国庆福
人工智能·算法·机器学习·语言模型·paddlepaddle
dengqingrui12341 分钟前
【树形DP】AT_dp_p Independent Set 题解
c++·学习·算法·深度优先·图论·dp
C++忠实粉丝42 分钟前
前缀和(8)_矩阵区域和
数据结构·c++·线性代数·算法·矩阵
ZZZ_O^O1 小时前
二分查找算法——寻找旋转排序数组中的最小值&点名
数据结构·c++·学习·算法·二叉树
CV-King2 小时前
opencv实战项目(三十):使用傅里叶变换进行图像边缘检测
人工智能·opencv·算法·计算机视觉
代码雕刻家2 小时前
数据结构-3.9.栈在递归中的应用
c语言·数据结构·算法
Kalika0-04 小时前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
sp_fyf_20244 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-02
人工智能·神经网络·算法·计算机视觉·语言模型·自然语言处理·数据挖掘
我是哈哈hh6 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝