当前位置: 首页 > news >正文

算法沉淀五:位运算

位运算内容总结

1.基础位运算

<<  >> ~  

&:有0就是0

| :有1就是1

^:相同为0,相异为1 / 无进位相加

2.给一个数n,确定它的二进制表示中的第x位是0还是1

&上一个1,要么让第x位右移,要么让1左移,一般用右移x位,  (n>>x)&1

3.将一个数n的二进制表示的第x位修改成1

n |= (1<<x)     等价于  n = n | (1 << x)

4.将一个数n的二进制表示的第x位修改为0

n &= ~(1<<x)     1左移之后按位取反

5.位图的思想

2,3,4其实就是一类问题,本质就是一个哈希表,很多情况下就是一个数组。位图就是用一个整形变量的二进制比特位来记录信息。

6.提取一个数(n)二进制表示中最右侧的1(lowbit)

n & -n 

如何表示-n:n的按位取反再加1,本质就是将最右侧的1的左边区域全部变成相反。

7.去掉一个数(n)二进制表示中最右侧的1

n & (n - 1) 

n-1:将最右侧的1的右边的区域(包含1)全部取反

8.位运算的优先级

能加括号就加括号

9.异或(^)运算的运算律

1. a ^ 0 = a

2. a ^ a = 0

3. a ^ b ^ c = a ^ (b ^ c)

面试题01.01.判断字符是否唯一【简单】

力扣链接

实现一个算法,确定一个字符串 s 的所有字符是否全都不同。

示例 1:输入: s = "leetcode" 输出: false

示例 2:输入: s = "abc" 输出: true

限制:

  • 0 <= len(s) <= 100
  • s[i]仅包含小写字母
  • 如果你不使用额外的数据结构,会很加分

解法一:哈希表

解法二:位图

优化点:鸽巢原理(抽屉原理)

如果字符串长度>26个字母,必定有一个字符是重复的。

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 >> i) & 1 == 1)) return false;
            else bitMap |=(1<<i);//此时位图中没有这个字符,所以将i位的位图设置位1
        }
        return true;
    }
};

268.消失的数字【简单】

力扣链接

给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。

示例 1:

输入:nums = [3,0,1]

输出:2

解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。

示例 2:

输入:nums = [0,1]

输出:2

解释:n = 2,因为有 2 个数字,所以所有的数字都在范围 [0,2] 内。2 是丢失的数字,因为它没有出现在 nums 中。

示例 3:

输入:nums = [9,6,4,2,3,5,7,0,1]

输出:8

解释:n = 9,因为有 9 个数字,所以所有的数字都在范围 [0,9] 内。8 是丢失的数字,因为它没有出现在 nums 中。

解法一:哈希表

解法二:高斯求和公式

解法三:位运算(异或):补齐数组再异或

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

137.只出现一次的数字Ⅱ 

力扣链接

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。

示例 1:输入:nums = [2,2,3,2] 输出:3

示例 2:输入:nums = [0,1,0,1,0,1,99] 输出:99

思路: 

  1. 逐位处理:遍历整数的每一位(共32位,因为int类型占32位)。

  2. 统计每位1的次数:对于每一位,统计数组中所有数字在该位上1出现的总次数。

  3. 取模确定结果位:由于其他数字出现三次,该位的总次数对3取余即为唯一数字在该位的值(0或1)。

  4. 组合结果:将各二进制位的值组合,得到最终结果。

int singleNumber(vector<int>& nums) {
    int res = 0;
    for (int i = 0; i < 32; ++i) { // 遍历每一位(0到31)
        int cnt = 0;
        for (auto x : nums) { // 统计所有数字在第i位的1的总数
            cnt += (x >> i) & 1; // 取出x的第i位,累加到cnt
        }
        res |= (cnt % 3) << i; // 取余得到结果位,合并到res
    }
    return res;
}

371.两整数之和

力扣链接

给你两个整数 a 和 b ,不使用 运算符 + 和 - ,计算并返回两整数之和。

示例 1:输入:a = 1, b = 2 输出:3

示例 2:输入:a = 2, b = 3 输出:5

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

面试题17.19 消失的两个数字

力扣链接

给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗?

以任意顺序返回这两个数字均可。

示例 1:输入:[1] 输出:[2,3]

示例 2:输入:[2,3] 输出:[1,4]

class Solution {
public:
    vector<int> missingTwo(vector<int>& nums) {
        //1.将所有的数异或在一起
        int tmp = 0;
        for (auto x : nums) tmp ^= x;
        for (int i = 0; i <= nums.size() + 2; i++) tmp ^= i;

        //2.找出a,b中比特位不同的那一位
        int diff = 0;
        while(1)
        {
            if (((tmp >> diff) & 1) == 1) break;
            else diff++;
        }
        //3.根据diff位的不同,将所有的数划分为两类来异或
        int a = 0, b = 0;
        for (int 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};
    }
};

相关文章:

  • 【Python 数据结构 15.哈希表】
  • JVM 2025/3/14
  • python-54-使用环境变量库python-dotenv进行应用程序配置参数的管理
  • 红色警戒2:共和国之辉红警语音台词是什么?
  • 【Vue.js】
  • docker python:latest镜像 允许ssh远程
  • VUE的脚手架搭建引入类库
  • 使用excel4node向excel批量写入图片
  • 2024 年第四届高校大数据挑战赛-赛题 A:岩石的自动鉴定
  • datax源码分析
  • 一个网络安全产品设计文档
  • Java高级-03.反射-获取构造器对象并使用
  • kali常用命令
  • Vue3使用ECharts入门示例
  • C++初阶——类和对象(一)
  • ArcGIS助力水文分析:数据处理、地图制作与流域特征提取
  • Linux--普通文件的管理
  • 如何让你的应用在市场中脱颖而出?
  • vscode远程连接服务器并运行项目里的.ipynb文件 如何在 Jupyter Notebook 中切换/使用 conda 虚拟环境?
  • 【计算机网络通信 MQTT和AMQP的原理及应用场景、优缺点】
  • 定制基因编辑疗法治愈罕见遗传病患儿
  • 外企聊营商|武田制药:知识产权保护助创新药研发
  • 中国青年报:为见义勇为者安排补考,体现了教育的本质目标
  • 湃书单|澎湃新闻编辑们在读的14本书:后工作时代
  • 中国证券业协会修订发布《证券纠纷调解规则》
  • 人民网三评“网络烂梗”:莫让低级趣味围猎青少年