算法之位运算
前言
位运算在我们的学习中占有很重要的地位,从二进制中数的存储等都需要我们进行位运算
一、位运算复习
1.位运算复习
按位与(&):如果两个相应的二进制位都为1,则该位的结果值才为1,否则为0
按位或( | ):如果两个相应的二进制位中有一个为1,则该位的结果值为1,否则为0
按位异或( ^ ):如果两个相应的二进制位值相同,则该位的结果值为0,否则为1
按位取反( ~ ):对二进制数按位取反,即0变为1,1变为0

其中我们使用最多的为异或操作, 异或操作又可以称为无进位相加。

2.常见的位操作
1.异或的运算规则
1. 两个相同的数异或结果为0
2. 异或满足交换律
3. 任何数异或0都为那个数本身

2.获得一个数的相反数
这个数取反加1为这个数的相反数,即( -num = (~num + 1) )

3.获得一个数中二进制位最右侧的1
这个数和它的相反数按位与,即( num &= -num)

其他的操作我们在下面补充
二、位运算练习
1.不创建第三变量进行交换两个数的值
void Swap()
{int a = 10;int b = 20;printf("交换前:a = %d,b = %d\n", a, b);a = a ^ b;b = a ^ b;a = a ^ b;printf("交换后:a = %d,b = %d\n", a, b);
}

此时用的是相同的数异或为0,0异或任何数都为那个数
注意,异或操作值可以相同,但不可以对同一块空间的值进行异或,否则会变为0,比如同时对a进行异或。
测试结果:

相关练习
2.不使用比较操作返回较大的数
void Compare()
{int a = 10;int b = 20;int c = a - b;int sya = ((a >> 31) & 1);//获得a的符号位int syb = ((b >> 31) & 1);//获得b的符号位int syc = ((c >> 31) & 1);//获得c的符号位int dif = sya ^ syb;//判断a和b的符号位是否相同//符号位相同则不会产生溢出if (dif == 0){if (syc == 1){printf("最大值为:%d\n", b);}else{printf("最大值为:%d\n", a);}}//可能会产生溢出else{if (sya == 1 && syb == 0){printf("最大值为:%d\n", b);}else{printf("最大值为:%d\n", a);}}
}
测试结果:

注意,两个数相加或者相减都可能产生溢出的情况,下面以char为例:

又比如:

所以这个需要我们进行判断是否会进行溢出,这个直接返回两个数相减的结果是否大于0在溢出情况下并不适用。
练习操作
3.不使用加减乘除等符号进行相应的操作
1.加法
//加法
int Add(int a, int b)
{int sum = a;while (b != 0){sum = a ^ b;//获得要进行进位的位置b = (a & b) << 1;a = sum;}
}

测试结果:

我们异或是不进位相加,所以下面两个数进行与是找到这两数都为1的位置,进行右移在异或相当于向前进1。
2.减法
//减法
int Sub(int a, int b)
{//获得b的相反数int sum = Add(~b, 1);//a和b的相反数进行相加sum = Add(a, sum);return sum;
}
测试结果:

在这里我们可以同通过我们的add函数来得到我们的所要的相反数,原理就是我们的按位取反加1得到
3.乘法
//乘法
int Mul(int a, int b)
{int sum = 0;while (b != 0){if ((b & 1) != 0)//b当前最右侧的是否为1{sum = Add(sum, a);}//模拟相乘的过程a <<= 1;//a进行右移b >>= 1;//b进行左移}return sum;
}
测试结果:

原理:二进制的乘法和十进制的乘法相同,在这里我们把十进制相乘转换为二进制相乘,我们可以通过移位来获得每个相加的数

4.除法
//除法
int div(int a, int b)
{int x = a < 0 ? Add(~a, 1) : a;int y = b < 0 ? Add(~b, 1) : b;int sum = 0;int i = 0;//从第31位开始进行判断for (i = 31; i > -1; i = Sub(i, 1)){if ((x >> i) >= y){sum |= (1 << i);x = Sub(x, y << i);}}return ((a < 0) ^ (b < 0)) ? Add(~sum, 1) : sum;
}
int Div(int a, int b)
{if (b == 0){//0为除数,结束程序exit(-1);}if (a == INT_MIN && b == INT_MIN){return 1;}else if (b == INT_MIN){return 0;}else if (a == INT_MIN){int sum = div(Add(a, 1), b);sum = Add(sum, div(Sub(a, Mul(sum, b)), b));return sum;}else{return div(a, b);}
}
测试结果:

原理:

注意:移动时要注意溢出情况,和除数是否为0。
4.整数二进制中1的个数
void Sum1()
{int a = 20;int sum = 0;while (a != 0){a &= (a - 1);sum++;}printf("1的个数为%d个\n", sum);
}

从上面可以看出我们的( a &= (a - 1) )操作是为了消除1
测试结果:

题目练习
5.在其他数都出现两次的数组中找出现一次的一个数
void Single_num()
{int arr[] = { 1,1,2,2,3,4,4,5,5,6,6 };int sum = 0;int i = 0;for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){sum ^= arr[i];}printf("出现一次的数%d\n", sum);
}
这个就是我们使用的交换律,和两个相同的数异或结果为0
测试结果:

练习题目
6.在其他数都出现两次的数组中找出现一次的两个数
void two_Single_num()
{int arr[] = { 1,1,2,2,3,4,5,5,6,6 };int sum = 0;int i = 0;for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){//找到这两个出现一次的数sum ^= arr[i];}//获得这两数异或结果最右侧的1,这个1也是这两个数不相同的位置int sum1 = sum & (~sum + 1);int sum2 = 0;for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){//&的优先级低于 ==//把和这个不相同的一位的值进行按位与,如果结果为0;则可以分为1组if ((sum1 & arr[i]) == 0){//得到的为其中的一位sum2 ^= arr[i];}}printf("出现一次的数%d %d\n", sum^sum2,sum2);
}
测试结果:


题目练习
7.在其他数都出现K次的数组中找出现一次的数
void k_Single_num()
{int arr[] = { 5, 4, 1, 1, 5, 1, 5 };int k = 3; int x = 0;int a[32] = { 0 };for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){//把数组中的数的每个进制位都进行相加x = arr[i];for (int j = 31; j >= 0; j--) {if (x & 1)a[j]++;x >>= 1;}}x = 0;for (int i = 0; i < 32; i++) {//对我们相加的值的每一个进制位进行相应的取模运算就是我们所要的值了x <<= 1;x += a[i] % k;}printf("%d\n", x);
}
测试结果:

原理:

我们可以看到在我们第i位置的值为((a[i] + b[i]) % 5),同理,在K进制中的两个数在i位上的无进位相加结果位((a[i] + b[i]) % K),所以k个相同的K进制位相加,那么相加后的结果每一位都为0。所以我们把出现的次数设置成相应的K进制位,最后把相加的结果转化为10进制就是我们所需要的值。
题目练习
总结
位运算还有许多的题目,大家可以在下面找着练习一下。
相关文章:
算法之位运算
前言 位运算在我们的学习中占有很重要的地位,从二进制中数的存储等都需要我们进行位运算 一、位运算复习 1.位运算复习 按位与(&):如果两个相应的二进制位都为1,则该位的结果值才为1,否则为0 按位或( | ):如果…...
flask使用Flask-Mail实现邮件发送
Flask-Mail可以实现邮件的发送,并且可以和 Flask 集成,让我们更方便地实现此功能。 1、安装 使用pip安装: $ pip install Flask-Mail或下载源码安装: $ git clone https://github.com/mattupstate/flask-mail.git $ cd flask-…...
React refers to UMD global, but the current file is a module vite初始化react项目
vite搭建react项目 初始化项目 npm create vite 在执行完上面的命令后,npm 首先会自动下载create-vite这个第三方包,然后执行这个包中的项目初始化逻辑。输入项目名称之后按下回车,此时需要选择构建的前端框架: ✔ Project na…...
vscode 调试 ROS2
1、在下列目录同层级找到.vscode文件夹 . ├── build ├── install ├── log └── src 2、 安装ros插件 3、创建tasks.json文件,添加下列内容 //代替命令行进行编译 {"version": "2.0.0","tasks": [{"label": &…...
TuyaOS开发学习笔记(2)——NB-IoT开发SDK架构、运行流程
一、SDK架构 1.1 架构框图 基于 TuyaOS 系统,可以裁剪得到的适用于 NB-IoT 协议产品接入的 SDK。SDK 将设备配网、上下行数据通信、产测授权、固件 OTA 升级等接口进行封装,并提供相关函数。 1.2 目录结构 1.2.1 TuyaOS目录说明 adapter:T…...
Qt应用开发(基础篇)——普通按钮类 QPushButton QCommandLinkButton
一、前言 QPushButton类继承于QAbstractButton,是一个命令按钮的小部件。 按钮基类 QAbstractButton 按钮或者命令按钮是所有图形界面框架最常见的部件,当按下按钮的时候触发命令、执行某些操作或者回答一个问题,典型的按钮有OK,A…...
Data Structures Fan(cf)
考察异或运算以及前缀和 题意大概:给你一个长度为n的a数组,一个长度为n的01字符串,会询问q次 当x的值为1 给出 l r 将 l r 区间中的0 改变为1,1改变为0 。当x的值为2是 若随后的数为0 则输出当前字符串中 是0 的a数组中的数异或 …...
BIOS < UEFI
Basic Input Output System (BIOS) Unified Extensible Firmware Interface (UEFI)...
微信最新更新隐私策略(2023-08-15)
1、manifest.json 配置修改 在mp-weixin: 参数修改(没有就添加) "__usePrivacyCheck__": true, ***2、注意 微信开发者工具调整 不然一直报错 找不到 getPrivacySetting 废话不多说 上代码 3、 编辑首页 或者用户授权界面 <uni-popup…...
Java中xml转javaBean
Java中xml转javaBean maven坐标 <dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId><version>2.13.4</version></dependency>代码测试 import cn.hutool.js…...
Spring Boot集成JPA和ClickHouse数据库
简介 Spring Boot是一个用于创建独立的、基于Spring的应用程序的框架。它具有快速开发特性,可以大大减少开发人员的工作量。JPA(Java Persistence API)是Java中处理关系型数据库持久化的标准规范,而ClickHouse是一个高性能、分布…...
Hadoop生态圈中的Hive数据仓库技术
Hadoop生态圈中的Hive数据仓库技术 一、Hive数据仓库的基本概念二、Hive的架构组成三、Hive和数据库的区别四、Hive的安装部署五、Hive的基本使用六、Hive的元数据库的配置问题七、Hive的相关配置项八、Hive的基本使用方式1、Hive的命令行客户端的使用2、使用hiveserver2方法操…...
idea配置gitLab
前言:网上有很多类似的文章,但描述不够详细 步骤1:安装git 如果安装成功再次点击TEST按钮展示如下:git版本 步骤2:idea配置gitlab 查看当前项目管理的 远程仓库再git的地址,该地址可是gitLab的࿰…...
工程可以编译通过,但是Vscode依然有波浪线提示
前言 (1)我们在使用Vscode进行开发的时候,命名文件成功编译通过了,但是Vscode还是有波浪线的提示。 (2)其实成功编译通过就行,但是肯定还会存在一些强迫症患者,硬要消除这个报错。接…...
黑马JVM总结(二)
(1)栈 栈帧对应一次方法的调用,线程是要执行代码的,这些代码都是由一个个方法组成,线程运行的时候每个方法需要的内存叫做一个栈帧 (2)栈的演示 Frames:相当有栈 方法相当于栈帧…...
《Effective C++中文版,第三版》读书笔记7
条款41: 了解隐式接口和编译期多态 隐式接口: 仅仅由一组有效表达式构成,表达式自身可能看起来很复杂,但它们要求的约束条件一般而言相当直接而明确。 显式接口: 通常由函数的签名式(也就是函数名…...
脚本:python实现动态爱心
文章目录 效果代码Reference python实现dynamic heart 效果 代码 import turtle as tu import random as ratu.setup(0.5, 0.5) # 设置画板大小(小数表示比例,整数表示大小) tu.screensize(1.0, 1.0) # 设置屏幕大小 tu.bgcolor(black) #…...
【李宏毅】深度学习6:机器学习任务攻略
如果在测试集上的效果不佳,应该要做什么?Optimization 如何选择?解决 overfitting 的方法? 测试集上的效果不佳 看训练数据的loss,是不是模型本身就没训练好? 问题:model 太简单了,…...
如何使用SQL SERVER的OpenQuery
如何使用SQL SERVER的OpenQuery 一、OpenQuery使用说明二、 OpenQuery语法2.1 参数说明2.2注解 三、示例3.1 执行 SELECT 传递查询3.2 执行 UPDATE 传递查询3.3 执行 INSERT传递查询3.4 执行 DELETE 传递查询 一、OpenQuery使用说明 在指定的链接服务器上执行指定的传递查询。 …...
element-tree树结构-默认选中第一个节点高亮-根据id选中节点高亮
前言 tree树结构是在开发中经常使用的组件,比如区域树,楼层树,组织架构树,等等包含节点关系 实际开发可能需要我们一进到页面选中树形结构第一个节点,并且调用数据,来达到用户体验 在用户选择之后&#x…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
