C++ 位运算OJ

目录

位运算常用操作:

1、 191. 位1的个数

2、 338. 比特位计数

3、 461. 汉明距离

 4、136. 只出现一次的数字

5、 260. 只出现一次的数字 III

6、面试题 01.01. 判定字符是否唯一

7、 268. 丢失的数字

8、 371. 两整数之和

9、 137. 只出现一次的数字 II

10、面试题 17.19. 消失的两个数字


位运算常用操作:

  • << 二进制左移一位
  • >> 二进制右移一位
  • ~   按位取反
  • &   有0则0
  • |     有1则1
  • ^     相同为0,相异为1,无进位相加

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

  • (n>>x)&1或者n&(1<<x)

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

  • n|=(1<<x)

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

  • n&=(~(1<<x))

5.位图的思想

  • 例如:使用整形变量int的每一个二进制位进行记录

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

  • n&-n

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

  • n&=(n-1)

8.位运算的优先级

  • 加括号解决

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

  • a^a=0
  • a^0=a
  • a^b^c=a^(b^c)
     

1、 191. 位1的个数

思路:干掉一个数(n)二进制表示中最右侧的1

  • n&=(n-1)
class Solution {
public:
    int hammingWeight(uint32_t n) {
        int ret = 0;
        while (n) {
            n &= (n - 1);
            ret++;
        }
        return ret;
    }
};

2、 338. 比特位计数

 思路:干掉一个数(n)二进制表示中最右侧的1 n&=(n-1)

class Solution {
public:
    vector<int> countBits(int n) {
        vector<int> a(n+1);
        for (int i = 0; i <= n; i++) {
            int ret = 0;
            int n = i;
            while (n) {
                n &= (n - 1);
                ret++;
            }
            a[i]=ret;
        }
        return a;
    }
};

3、 461. 汉明距离

思路:干掉一个数(n)二进制表示中最右侧的1 n&=(n-1)

class Solution {
public:
    int hammingDistance(int x, int y) {
        int n = x ^ y;
        int count = 0;
        while (n) {
            n &= (n - 1);
            count++;
        }
        return count;
    }
};

 4、136. 只出现一次的数字

思路:异或,所以元素进行异或,出现两次的会变为0,0不影响异或结果,所以剩下的就是出现一次的数。 

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int v=0;
        for(auto a:nums)
        {
            v^=a;
        }
        return v;
    }
};

5、 260. 只出现一次的数字 III

思路:所有元素异或后,取结果中任意一个二进制位为1的那一位,一定存在两组数,一组这一位为1,另一组这一位为0,由这一位可以分出两组数,这两组数中出现两次的数会抵消为0,最后两组分别剩下的就是出现一次的数。

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        int sum = 0;
        for (int num : nums) {
            sum ^= num;
        }
        // 防止溢出
        int l = (sum == INT_MIN ? sum : sum & (-sum));
        int num1 = 0, num2 = 0;
        for (int num : nums) {
            if (num & l)
                num1 ^= num;
            else
                num2 ^= num;
        }
        return {num1, num2};
    }
};
  • 首先,sum 是通过对数组中的所有元素进行异或操作得到的。由于其他元素都出现了两次,所以异或操作会将相同的元素抵消掉,最终得到的结果就是只出现一次的两个元素的异或值。

  • sum & (-sum) 的作用是获取 sum 的最低位的 1 所对应的值。-sum 是 sum 的补码的负数,它的二进制表示中只有最低位的 1 是相同的,其他位都是相反的。通过与操作 sum & (-sum),可以将 sum 的二进制表示中除了最低位的 1 以外的其他位都置为 0,得到的结果就是最低位的 1 所对应的值。

这样,l 就表示了只出现一次的两个元素在最低位的不同之处。在后续的循环中,根据每个元素的最低位是否与 l 相同,将元素分为两组,分别进行异或操作,最终得到的 num1 和 num2 就是只出现一次的两个元素。

需要注意的是,由于 INT_MIN 的二进制表示中只有最高位是 1,其他位都是 0,所以在计算 l 的时候需要特殊处理 sum == INT_MIN 的情况,因为 -INT_MIN 会导致溢出,以确保最低位的 1 能够正确地被提取出来。(在一个32位系统中,int 类型的数值范围通常是从 -2^31 到 2^31 - 1,也就是从 -2147483648 到 2147483647。)

-INT_MIN为2^31大于整形最大值2^31-1.

INT_MIN 的二进制形式是一个以 1 开头,后面跟着 31 个 0 的二进制数。在大多数平台上,INT_MIN 的二进制表示为:10000000000000000000000000000000

这是一个带符号的 32 位整数,最高位为 1,表示负数,其余位为 0。这是 int 类型能够表示的最小值。

6、面试题 01.01. 判定字符是否唯一

 

思路:位图思想,int类型变量有32个比特位,选取26个比特位记录字母判断是否每个字母只出现一次。 

class Solution {
public:
    bool isUnique(string astr) {
        if (astr.size() > 26)
            return false;
        int bitmap = 0;
        for (auto s : astr) {
            int i = s - 'a';
            if ((bitmap >> i) & 1 == 1)
                return false;
            else
                bitmap |= (1 << i);
        }
        return true;
    }
};

假设我们有一个字符串 astr = "abcde",并且我们使用一个 32 位的整数 bitmap 来表示字符是否出现过。在这个例子中,每个字符都对应一个整数,假设 'a' 对应 0,'b' 对应 1,以此类推。

初始时,bitmap 的二进制表示是 000...000,全部为 0。然后我们遍历字符串 astr 中的每个字符,检查是否出现过。

  1. 对于字符 'a':

    • 字符 'a' 对应整数 0。
    • 计算 bitmap >> 0,结果还是 000...000
    • 执行 (bitmap >> 0) & 1,结果为 0,说明 'a' 还没有出现过。
    • 将 bitmap |= (1 << 0),将 'a' 对应的位置设为 1,此时 bitmap 的二进制表示变为 000...001
  2. 对于字符 'b':

    • 字符 'b' 对应整数 1。
    • 计算 bitmap >> 1,结果为 000...000
    • 执行 (bitmap >> 1) & 1,结果为 0,说明 'b' 还没有出现过。
    • 将 bitmap |= (1 << 1),将 'b' 对应的位置设为 1,此时 bitmap 的二进制表示变为 000...011
  3. 对于字符 'c':

    • 字符 'c' 对应整数 2。
    • 计算 bitmap >> 2,结果为 000...000
    • 执行 (bitmap >> 2) & 1,结果为 0,说明 'c' 还没有出现过。
    • 将 bitmap |= (1 << 2),将 'c' 对应的位置设为 1,此时 bitmap 的二进制表示变为 000...111

依此类推,遍历完字符串后,bitmap 的二进制表示可能变为 000...111,因为所有字符都出现过。如果字符串长度超过 26,说明一定有重复字符,那么函数会返回 false

7、 268. 丢失的数字

 思路:两次异或

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;
    }
};

8、 371. 两整数之和

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

9、 137. 只出现一次的数字 II

 思路:

  1. 创建一个长度为 32 的整数数组 count,用于记录每一位上的出现次数。
  2. 遍历数组 nums 中的每个元素,对每个元素的每一位进行统计,即将每个元素的每一位与 1 进行与操作,然后根据结果更新对应位的计数器。
  3. 对每一位上的计数器进行模 3 操作,因为除了只出现一次的元素,其他元素都出现三次,所以对每一位上的计数取模 3 之后,剩余的结果就是只出现一次的元素在该位上的值。
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ret = 0;
        for (int i = 0; i < 32; i++) {
            int sum = 0;
            for (auto n : nums) {
                if (((n >> i) & 1) == 1)
                    sum++;
            }
            sum %= 3;
            if (sum == 1)
                ret |= 1 << i;
        }
        return ret;
    }
};

10、面试题 17.19. 消失的两个数字

思路:

  1. 异或操作统计缺失的两个数字:

    • 我们首先遍历给定数组 nums,对其中的每个元素执行异或操作,得到一个结果 tmp。由于数组中缺失了两个数字,所以 tmp 最终将包含这两个缺失的数字的异或结果。
    • 接着,我们对从 1 到 N+2 的所有整数执行异或操作,得到的结果也存储在 tmp 中。这样,tmp 中存储的就是缺失的两个数字的异或结果,因为在从 1 到 N+2 的所有整数中,只有这两个数字出现了奇数次,其他数字出现了偶数次,所以它们会保留下来。
  2. 确定两个缺失的数字:

    • 接下来,我们需要找到 tmp 中哪一位上的值为 1,因为在这一位上,两个缺失的数字不同,通过这一位可以将它们区分开来。我们通过一个循环来找到这个位置 d,使得 tmp 的第 d 位为 1。
    • 然后,我们再次遍历数组 nums 和从 1 到 N+2 的所有整数,根据第 d 位的值将它们分成两组,分别执行异或操作,最终得到的就是两个缺失的数字 a 和 b
  3. 返回结果:

    • 最后,我们将 a 和 b 组成一个数组返回即可。

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;
        }
        int d = 0;
        while (((tmp >> d) & 1) != 1) {
            d++;
        }
        int a = 0, b = 0;
        for (auto x : nums) {
            if (((x >> d) & 1) == 1)
                a ^= x;
            else
                b ^= x;
        }
        for (int i = 1; i <= nums.size() + 2; i++) {
            if (((i >> d) & 1) == 1)
                a ^= i;
            else
                b ^= i;
        }
        return {a, b};
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/433514.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++实战项目】Date日期类 --- 运算符重载的深入探索

&#x1f4f7; 江池俊&#xff1a;个人主页 &#x1f525; 个人专栏&#xff1a;✅C那些事儿 ✅Linux技术宝典 &#x1f305; 此去关山万里&#xff0c;定不负云起之望 文章目录 引言一、为什么需要运算符重载&#xff1f;二、日期类的实现1. 基本框架2. 预备工作3. Date 类…

海外媒体发稿:提升国外影响力的7种汽车媒体推广方法-华媒舍

伴随着全球化发展的推动&#xff0c;汽车市场已经变成世界各地关注的重点领域之一。提升汽车知名品牌在海外的影响力对于企业的发展趋势尤为重要。下面我们就详细介绍7种提升国外影响力的汽车媒体推广方法&#xff0c;协助汽车公司能够更好地进到国外市场。 1.公布知名品牌新闻…

Vue中有哪些优化性能的方法?

Vue是一款流行的JavaScript框架&#xff0c;用于构建交互性强的Web应用程序。在前端开发中&#xff0c;性能优化是一个至关重要的方面&#xff0c;尤其是当应用程序规模变大时。Vue提供了许多优化性能的方法&#xff0c;可以帮助开发人员提升应用程序的性能&#xff0c;从而提升…

【ESP32 IDF】I2C层次结构、I2C协议

文章目录 前言一、I2C的结构层次1.1 怎样在两个设备之间传输数据1.2 I2C如何传输数据1.3 硬件框图1.4 软件层次 二、IIC协议2.1 硬件连接2.2 I2C 总线的概念2.3 传输数据类比2.3 I2C信号2.4 I2C数据的含义 总结 前言 I2C&#xff08;Inter-Integrated Circuit&#xff09;是一…

第 5 章 ROS常用组件静态坐标变换(自学二刷笔记)

5.1.2 静态坐标变换 所谓静态坐标变换&#xff0c;是指两个坐标系之间的相对位置是固定的。 需求描述: 现有一机器人模型&#xff0c;核心构成包含主体与雷达&#xff0c;各对应一坐标系&#xff0c;坐标系的原点分别位于主体与雷达的物理中心&#xff0c;已知雷达原点相对于…

【好书推荐-第九期】Sora核心技术相关书籍《扩散模型:从原理到实战》与《GPT 图解:大模型是怎样构建的》:Sora的两大核心技术,都藏在这两本书里!

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主、前后端开发、人工智能研究生。公众号&#xff1a;洲与AI。 &#x1f388; 本文专栏&#xff1a;本文收录…

《Vite 报错》ReferenceError: module is not defined in ES module scope

ReferenceError: module is not defined in ES module scope 解决方案 postcss.config.js 要改为 postcss.config.cjs&#xff0c;也就是 .cjs 后缀。 原因解析 下图提示&#xff0c;packages.json 中的属性 type 设置为 module。所有 *.js 文件现在都被解释为 ESM&#xff…

【vue/组件封装】封装一个带条件筛选的搜索框组件(多组条件思路、可多选)详细流程

引入&#xff1a;实现一个带有筛选功能的搜索框&#xff0c;封装成组件&#xff1b; 搜索框长这样子&#xff1a; 点击右侧筛选图标后弹出层&#xff0c;长这样子&#xff1a; 实际应用中有多组筛选条件&#xff0c;这里为了举栗子就展示一组&#xff1b; 预览&#xff1a;…

Windows环境中Domain Controller (域控制器)的搭建,零基础教学详细教程

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;网络安全渗透 景天的主页&#xff1a;景天科技苑 文章目录 1.搭建域环境2.搭建过程2.1.安装域控2.2.建立域的普通用户2.3.把…

BUUCTF:[MRCTF2020]ezmisc

题目地址&#xff1a;https://buuoj.cn/challenges#[MRCTF2020]ezmisc 下载附件打开是一张照片&#xff1a; 放到kali中发现crc校验错误&#xff0c;修改照片宽高&#xff1a; 保存即可发现flag flag为&#xff1a; flag{1ts_vEryyyyyy_ez!}

为什么MySQL中多表联查效率低,连接查询实现的原理是什么?

MySQL中多表联查效率低的原因主要涉及到以下几个方面&#xff1a; 数据量大: 当多个表通过连接查询时&#xff0c;如果这些表的数据量很大&#xff0c;那么查询就需要处理更多的数据&#xff0c;这自然会降低查询效率。 连接操作复杂性: 连接查询需要对参与连接的每个表中的数…

HTTPS是什么,那些行业适合部署呢?

随着在线活动的增加&#xff0c;对您共享的关键数据的威胁已经产生了严重的后果&#xff0c;包括欺诈性金融交易、在线身份盗窃等。此外&#xff0c;随着技术使用的增加&#xff0c;网络攻击也变得更加复杂和具有挑战性。 毫无疑问&#xff0c;互联网用户的数据安全意识成倍增长…

QVector和QString互相转换

我的画图项目需要读写自定义虚线样式 {...comboBox_penStyle new QComboBox;QStringList SL_penStyle;SL_penStyle << "______" << "----------" << ".........." << "-.-.-.-.-." << "-..-..-..…

openEuler 社区 2024 年 2 月运作报告

概述 2024年2月中旬&#xff0c;OpenAtom openEuler&#xff08;简称"openEuler"&#xff09;2023 社区年报发布。这是社区开源四年来&#xff0c;在生态构建、技术创新、产业聚集、人才培养等方面发展的成果展示&#xff0c;也是社区1400多家成员单位、1.7万多名开…

前面说什么是前后端分类,那到底是怎么个分类法呢?

前后端分离是指将一个web 系统的动态内容和静态内容进行分离&#xff0c;包括其开发、部署等。 比如传统的 MVC 架构&#xff0c;HTML、JS、CSS… 等前端代码和 Java、spring、mybatis… 等后端代码是在同一个项目中进行开发、部署的。那前后端分离后&#xff0c;就可以分多个项…

深入浅出解析SSL:保障网络安全的加密技术

在数字信息时代&#xff0c;网络安全已成为人们关注的重点。为了在网络传输过程中保护数据的完整性和机密性&#xff0c;我们需要一种强大的安全协议——SSL&#xff08;安全套接层&#xff09;。今天德迅云安全就带大家来简单了解下SSL是什么&#xff0c;它的工作原理以及为何…

Java中常见延时队列的实现方案总结

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&…

Intel RealSense D435环境搭建之安装pyrealsense2

ERROR: Could not find a version that satisfies the requirement pyrealsense2 (from versions: none) pip install pyrealsense2 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com 方法一&#xff1a;升级pip python -m pip install --upgrade pip 方…

Redis第6讲——主从复制模式详解

Redis的读写性能很高&#xff0c;但在面对大规模数据和高发访问的挑战时&#xff0c;单节点的Redis可能无法满足需求&#xff0c;这就引出了Redis集群的概念。本节先介绍一下Redis高可用方案之一的主从复制模式&#xff0c;虽说现在基本不会用这种模式&#xff0c;但是无论是哨…

【VTKExamples::PolyData】第四十九期 Silhouette

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 前言 本文分享VTK样例Silhouette,并解析接口vtkPolyDataSilhouette,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 1. Silhouett…