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

算法之位运算

前言

位运算在我们的学习中占有很重要的地位,从二进制中数的存储等都需要我们进行位运算

一、位运算复习

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进制就是我们所需要的值。

题目练习

总结

位运算还有许多的题目,大家可以在下面找着练习一下。

相关文章:

算法之位运算

前言 位运算在我们的学习中占有很重要的地位&#xff0c;从二进制中数的存储等都需要我们进行位运算 一、位运算复习 1.位运算复习 按位与(&)&#xff1a;如果两个相应的二进制位都为1&#xff0c;则该位的结果值才为1&#xff0c;否则为0 按位或( | )&#xff1a;如果…...

flask使用Flask-Mail实现邮件发送

Flask-Mail可以实现邮件的发送&#xff0c;并且可以和 Flask 集成&#xff0c;让我们更方便地实现此功能。 1、安装 使用pip安装&#xff1a; $ pip install Flask-Mail或下载源码安装&#xff1a; $ 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 在执行完上面的命令后&#xff0c;npm 首先会自动下载create-vite这个第三方包&#xff0c;然后执行这个包中的项目初始化逻辑。输入项目名称之后按下回车&#xff0c;此时需要选择构建的前端框架&#xff1a; ✔ Project na…...

vscode 调试 ROS2

1、在下列目录同层级找到.vscode文件夹 . ├── build ├── install ├── log └── src 2、 安装ros插件 3、创建tasks.json文件&#xff0c;添加下列内容 //代替命令行进行编译 {"version": "2.0.0","tasks": [{"label": &…...

TuyaOS开发学习笔记(2)——NB-IoT开发SDK架构、运行流程

一、SDK架构 1.1 架构框图 基于 TuyaOS 系统&#xff0c;可以裁剪得到的适用于 NB-IoT 协议产品接入的 SDK。SDK 将设备配网、上下行数据通信、产测授权、固件 OTA 升级等接口进行封装&#xff0c;并提供相关函数。 1.2 目录结构 1.2.1 TuyaOS目录说明 adapter&#xff1a;T…...

Qt应用开发(基础篇)——普通按钮类 QPushButton QCommandLinkButton

一、前言 QPushButton类继承于QAbstractButton&#xff0c;是一个命令按钮的小部件。 按钮基类 QAbstractButton 按钮或者命令按钮是所有图形界面框架最常见的部件&#xff0c;当按下按钮的时候触发命令、执行某些操作或者回答一个问题&#xff0c;典型的按钮有OK&#xff0c;A…...

Data Structures Fan(cf)

考察异或运算以及前缀和 题意大概&#xff1a;给你一个长度为n的a数组&#xff0c;一个长度为n的01字符串&#xff0c;会询问q次 当x的值为1 给出 l r 将 l r 区间中的0 改变为1&#xff0c;1改变为0 。当x的值为2是 若随后的数为0 则输出当前字符串中 是0 的a数组中的数异或 …...

BIOS < UEFI

Basic Input Output System &#xff08;BIOS&#xff09; Unified Extensible Firmware Interface &#xff08;UEFI&#xff09;...

微信最新更新隐私策略(2023-08-15)

1、manifest.json 配置修改 在mp-weixin: 参数修改&#xff08;没有就添加&#xff09; "__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的应用程序的框架。它具有快速开发特性&#xff0c;可以大大减少开发人员的工作量。JPA&#xff08;Java Persistence API&#xff09;是Java中处理关系型数据库持久化的标准规范&#xff0c;而ClickHouse是一个高性能、分布…...

Hadoop生态圈中的Hive数据仓库技术

Hadoop生态圈中的Hive数据仓库技术 一、Hive数据仓库的基本概念二、Hive的架构组成三、Hive和数据库的区别四、Hive的安装部署五、Hive的基本使用六、Hive的元数据库的配置问题七、Hive的相关配置项八、Hive的基本使用方式1、Hive的命令行客户端的使用2、使用hiveserver2方法操…...

idea配置gitLab

前言&#xff1a;网上有很多类似的文章&#xff0c;但描述不够详细 步骤1&#xff1a;安装git 如果安装成功再次点击TEST按钮展示如下&#xff1a;git版本 步骤2&#xff1a;idea配置gitlab 查看当前项目管理的 远程仓库再git的地址&#xff0c;该地址可是gitLab的&#xff0…...

工程可以编译通过,但是Vscode依然有波浪线提示

前言 &#xff08;1&#xff09;我们在使用Vscode进行开发的时候&#xff0c;命名文件成功编译通过了&#xff0c;但是Vscode还是有波浪线的提示。 &#xff08;2&#xff09;其实成功编译通过就行&#xff0c;但是肯定还会存在一些强迫症患者&#xff0c;硬要消除这个报错。接…...

黑马JVM总结(二)

&#xff08;1&#xff09;栈 栈帧对应一次方法的调用&#xff0c;线程是要执行代码的&#xff0c;这些代码都是由一个个方法组成&#xff0c;线程运行的时候每个方法需要的内存叫做一个栈帧 &#xff08;2&#xff09;栈的演示 Frames&#xff1a;相当有栈 方法相当于栈帧…...

《Effective C++中文版,第三版》读书笔记7

条款41&#xff1a; 了解隐式接口和编译期多态 隐式接口&#xff1a; ​ 仅仅由一组有效表达式构成&#xff0c;表达式自身可能看起来很复杂&#xff0c;但它们要求的约束条件一般而言相当直接而明确。 显式接口&#xff1a; ​ 通常由函数的签名式&#xff08;也就是函数名…...

脚本:python实现动态爱心

文章目录 效果代码Reference python实现dynamic heart 效果 代码 import turtle as tu import random as ratu.setup(0.5, 0.5) # 设置画板大小&#xff08;小数表示比例&#xff0c;整数表示大小&#xff09; tu.screensize(1.0, 1.0) # 设置屏幕大小 tu.bgcolor(black) #…...

【李宏毅】深度学习6:机器学习任务攻略

如果在测试集上的效果不佳&#xff0c;应该要做什么&#xff1f;Optimization 如何选择&#xff1f;解决 overfitting 的方法&#xff1f; 测试集上的效果不佳 看训练数据的loss&#xff0c;是不是模型本身就没训练好&#xff1f; 问题&#xff1a;model 太简单了&#xff0c…...

如何使用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树结构是在开发中经常使用的组件&#xff0c;比如区域树&#xff0c;楼层树&#xff0c;组织架构树&#xff0c;等等包含节点关系 实际开发可能需要我们一进到页面选中树形结构第一个节点&#xff0c;并且调用数据&#xff0c;来达到用户体验 在用户选择之后&#x…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

c# 局部函数 定义、功能与示例

C# 局部函数&#xff1a;定义、功能与示例 1. 定义与功能 局部函数&#xff08;Local Function&#xff09;是嵌套在另一个方法内部的私有方法&#xff0c;仅在包含它的方法内可见。 • 作用&#xff1a;封装仅用于当前方法的逻辑&#xff0c;避免污染类作用域&#xff0c;提升…...

用鸿蒙HarmonyOS5实现中国象棋小游戏的过程

下面是一个基于鸿蒙OS (HarmonyOS) 的中国象棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chinesechess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├──…...