算法通关村——位运算

1. 常见的位运算

1.1 与 &

&:两个数对应的位都是1,那么结果才是1
1 & 1 = 1
1 & 0 = 0;
0 & 0 = 0;

1.2 或 |

|: 只要两个数对应的位有一个1,结果就是1
1 | 1 = 1;
1 | 0 = 1;
0 | 0 = 0;

1.3 异或^

^: 只有两个数的位都一样的时候才是返回0,否则返回1
1 ^ 1 = 0
0 ^ 1 = 1
0 ^ 0 = 0;

1.4 取反 ~

~: 就是取反,如果位是1,取反就是0
~1=0
~0=1

2. 移位运算

左移:<< 全部二进制左移若干位(如果左移一位,就是除以2)
右移:>> 全部二进制右移若干位

3. 位1的个数

位1的个数
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。

3.1 右移

只需要将每一位和1进行与&操作,如果当前位是1,那么就计数
i=0 00000000000000000000000000001011 & …1=1
i=1 00000000000000000000000000000101 & …1=1
i=2 00000000000000000000000000000010 & …1=0
i=3 00000000000000000000000000000001 & …1=1

结果是3

 public int hammingWeight(int n) {int count =0;for(int i=0;i<32;i++){count+=(n>>i)&1;}return count;}

3.2 左移

先设置一个mask之用于左移比较是否位相同
00000000000000000000000000001011 & 1 =0
00000000000000000000000000001011 & 01 = 0
00000000000000000000000000001011 & 001 =0

00000000000000000000000000001011 & 00000000000000000000000000001 = 1
00000000000000000000000000001011 & 000000000000000000000000000001 = 0
00000000000000000000000000001011 & 0000000000000000000000000000001 = 1
00000000000000000000000000001011 & 00000000000000000000000000000001 = 1

 public int hammingWeight(int n) {int count =0;int mask = 1;for(int i=0;i<32;i++){if((n & mask) !=0){count++;}mask<<=1;}return count;}

3.3 n&(n-1)

将二进制最后一个1变成0,直到n最后变成0
00000000000000000000000000001011 & 00000000000000000000000000001010 = 00000000000000000000000000001010
count = 1;

00000000000000000000000000001010 & 00000000000000000000000000001001 = 00000000000000000000000000001000
count = 2;

00000000000000000000000000001000 & 00000000000000000000000000000111 =
0000000000000000000000000000000
count =3;

 public int hammingWeight(int n) {int count =0;while(n!=0){n=n&(n-1);count++;}return count;}

这种效率也是比较高的,经常使用,前两个位移都是需要遍历32次,而n&(n-1)只需要n为0的时候就退出
在这里插入图片描述

4. 比特位计数

比特位计数
给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。
输入:n = 2
输出:[0,1,1]
解释:
0 --> 0
1 --> 1
2 --> 10

4.1 右移

这里面的的计算1的个数就可以采用之前的( n>>i ) &1,其中n是当前的值,而i是右移的位数
很显然,因为元素大小是在0-n这个范围内,所以是按照相应下标就可以知道当前的值,那么再次&1比较,然后右移,就可以算出1的个数,然后赋值给数组。

    public int[] countBits(int n) {int [] res = new int [n+1];for(int i=0;i<=n;i++){for(int j=0;j<32;j++){res[i] += (i >>j)&1;}}return res;}

此方法缺点在于时间耗费比较长,因为每个元素都要遍历右移32次,才能计算1的个数

4.2 位的性质 n&(n-1)

public int[] countBits(int n) {int count =0;int [] res = new int [n+1];for(int i=0;i<=n;i++){res[i] = getOneCount(i);}return res;}public int getOneCount(int x){int count =0;while(x!=0){x=x&(x-1);count++;}return count;}

5. 颠倒二进制位

颠倒给定的 32 位无符号整数的二进制位。提示:请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在 示例 2 中,输入表示有符号整数 -3,输出表示有符号整数 -1073741825

5.1 逐位颠倒

一开始想的是直接反转这个二进制数,直接使用Integer的reverse是肯定不行的。
首先先获取到n的最后一位,然后n进行逻辑右移,和reversed反转数进行相加,直到n变成0
00000010100101000001111010011100右移31位,最低位是0
n逻辑右移1位
00000001010010100000111101001110右移30位,最低位是0

 public int reverseBits(int n) {int reversed =0;int length = 31;while(n!=0){reversed += (n&1)<<length;// 逻辑右移n >>>= 1;length--;}return reversed;}

6. 两整数之和

两整数之和
给你两个整数 a 和 b ,不使用 运算符 + 和 - ​​​​​​​,计算并返回两整数之和。
输入:a = 2, b = 3
输出:5

6.1 异或+与

2:010
3:011
5:101
可以看出相同为0,不同为1,这是异或,对于不需要进位的部分采用a^b , 但是需要关注首位是0还是1,进位部分就要采用a&b,只有两个都是1的时候才需要进位。

public int getSum(int a, int b) {while(b!=0){int sign = (a & b) << 1;a = a ^ b;b = sign;}return a;}

a&b= 010 010 << 1 = 100 sign = 100
a^b= 001 a = 001
b = 100

a&b = 100 & 001 = 000 000<1 =000 sign =0
a^b = 100 ^ 001 = 101 a = 101
b =0
退出

a=101 =5

7. 递归乘法

递归乘法
递归乘法。 写一个递归函数,不使用 * 运算符, 实现两个正整数的相乘。可以使用加号、减号、位移,但要吝啬一些。
输入:A = 3, B = 4
输出:12

7.1 位运算

例如3 * 4,就是3 * 2 ^ 2,也就是3<<2,左移两位
例如1 * 10,就是1 (2+8)就是1 * 2^1+12 ^3 就是1 <<1 +1<<3

先找出两者之间的最小值和最大值,选取最小值作为乘数的原因是次数较少,然后判断min的最右一位是不是1,是1就添加该位到结果中,然后最小值右移一位

 public int multiply(int A, int B) {int add = 0;int min = Math.min(A,B);int max = Math.max(A,B);for(int i=0;min!=0;i++){if((min & 1) == 1){add  += max<< i;}min >>= 1;}return add;}

例如 1 * 10 min = 1,max = 10, min &1 =1, add = 10 << 0 = 1010=10
min >>1 = 0 退出

例如 3* 4 min = 3 max =4 min & 1= 1 add = 4 << 0 =4
min >> 1 = 01 min & 1= 1 add = 4 + 4 << 1 = 4 + 8 = 12

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决访问Github出现的Couldn‘t connect to server错误

文章目录 前言原因分析以及解决办法原因分析解决办法 参考 前言 在Github上面克隆代码仓库出现Failed to connect to 127.0.0.1 port 1080 after 2063 ms: Couldnt connect to server、Failed to connect to github.com port 443 after 21083 ms: Couldnt connect to server等…

一百六十、Kettle——Linux上安装的Kettle9.2.0连接Hive3.1.2

一、目标 Kettle9.2.0在Linux上安装好后&#xff0c;需要与Hive3.1.2数据库建立连接 之前已经在本地上用kettle9.2.0连上Hive3.1.2 二、各工具版本 &#xff08;一&#xff09;kettle9.2.0 kettle9.2.0安装包网盘链接 链接&#xff1a;https://pan.baidu.com/s/15Zq9w…

Django框架 靓号管理(增删改查)

Django框架 靓号管理&#xff08;增删改查&#xff09; 新建一个项目 backend 使用pycharm创建app startapp app项目目录 C:\code\backend ├── app | ├── admin.py | ├── apps.py | ├── migrations | ├── models.py | ├── tests.py | ├── views.…

js实现按创建时间戳1609459200000 开始往后开始显示运行时长-demo

运行时长 00日 00时 17分 59秒 代码 function calculateRuntime(timestamp) {const startTime Date.now(); // 获取当前时间戳//const runtimeElement document.getElementById(runtime); // 获取显示运行时长的元素function updateRuntime() {const currentTimestamp Date…

1.物联网LWIP网络,TCP/IP协议簇

一。TCP/IP协议簇 1.应用层&#xff1a;FTP&#xff0c;HTTP&#xff0c;Telent&#xff0c;DNS&#xff0c;RIP 2.传输层&#xff1a;TCP&#xff0c;UDP 3.网络层&#xff1a;IPV4&#xff0c;IPV6&#xff0c;OSPF&#xff0c;EIGRP 4.数据链路层&#xff1a;Ethernet&#…

后端返回图片资源错误404,前端使用默认图片

后端返回的图片资源可能会因为各种原因&#xff08;后台误删&#xff0c;地址更改未及时更新&#xff0c;损毁&#xff09;出现无法展示的情况&#xff0c;比如这种报错 就会导致图片资源错误&#xff0c;页面出现这种情况 用户体验很不好&#xff0c;为了改善这种情况&#xf…

36.8k Star! 一款小而美的自动化运维监控工具——Uptime Kuma

自动化运维是指利用计算机科学和信息技术来实现系统和应用程序的自动化管理、监控、维护以及问题解决的过程。它的目标是减少人工干预、提高效率、降低错误率&#xff0c;并确保系统的稳定性和可靠性。 应用简览 Uptime-Kuma 是一个轻量级的监控工具&#xff0c;其独特之处在于…

5G科技防汛,助力守护一方平安

“立秋虽已至&#xff0c;炎夏尚还在”&#xff0c;受台风席卷以及季节性影响全国多地正面临强降水的严峻挑战。“落雨又顺秋&#xff0c;绵绵雨不休”&#xff0c;正值“七下八上” 防汛关键时期&#xff0c;贵州省水文水资源局已全面进入备战状态。 为确保及时响应做好防汛抢…

typedef

t y p e d e f typedef typedef 声明&#xff0c;简称typedef&#xff0c;是创建现有类型的新名字。 比如&#xff1a; #include <bits/stdc.h> using namespace std; typedef long long ll; int main() {ll n;scanf("%lld",&n);printf("%lld"…

echarts tooltip提示框加单位

效果&#xff1a; 1.比较简单的方法 series: [{name: "重大风险",type: "bar",data: data2,color: ExtremeRiskColor,tooltip: {valueFormatter: function (value) {return value 个;}},},{name: "较大风险",type: "bar",data: dat…

rabbitmq的消息应答

消费者完成一个任务可能需要一段时间&#xff0c;如果其中一个消费者处理一个长的任务并仅只完成 了部分突然它挂掉了&#xff0c;会发生什么情况。RabbitMQ 一旦向消费者传递了一条消息&#xff0c;便立即将该消 息标记为删除。在这种情况下&#xff0c;突然有个消费者挂掉了…

如何切换goland之中的版本号(升级go 到1.20)

go 安装/版本切换_go 切换版本_云满笔记的博客-CSDN博客 用brew就行&#xff1a; echo export PATH"/opt/homebrew/opt/go1.20/bin:$PATH" >> ~/.zshrc

HTML详解连载(7)

HTML详解连载&#xff08;7&#xff09; 专栏链接 [link](http://t.csdn.cn/xF0H3)下面进行专栏介绍 开始喽结构伪类选择器作用 :nth-child&#xff08;公式&#xff09;作用举例 伪元素选择器作用注意&#xff1a; PxCoook作用盒子模型-重要组成部分 盒子模型-边框线属性名属性…

Matlab中图例的位置(图例放在图的上方、下方、左方、右方、图外面)等

一、图例默认位置 默认的位置在NorthEast r 10; a 0; b 0; t0:0.1:2.1*pi; xar*cos(t); ybr*sin(t); A1plot(x,y,r,linewidth,4);%圆 hold on axis equal A2plot([0 0],[1 10],b,linewidth,4);%直线 legend([A1,A2],圆形,line)二、通过Location对legend的位置进行改变 变…

sykwalking8.2和mysql5.7快速部署

1.SkyWalking 是什么&#xff1f; 分布式系统的应用程序性能监视工具&#xff0c;专为微服务、云原生架构和基于容器&#xff08;Docker、K8s、Mesos&#xff09;架构而设计。 提供分布式追踪、服务网格遥测分析、度量聚合和可视化一体化解决方案。 2.SkyWalking 有哪些功能…

K8S之存储卷

K8S之存储卷 一、emptyDir emptyDir&#xff1a;可实现Pod中的容器之间共享目录数据&#xff0c;但emptyDir存储卷没有持久化数据的能力&#xff0c;存储卷会随着Pod生命周期结束而一起删除二、hostPath hostPath&#xff1a;将Node节点上的目录/文件挂载到Pod容器的指定目录…

LVS-DR模式下(RS检测)ldirectord工具实现部分节点掉点后将请求发往正常设备进行处理

基于前文的LVS-DR集群构建环境 一.下载ldirectord软件 二.将模板文件中的LVS-DR模式相关文件拷贝到/etc/ha.d主配置目录并按实际设备修改 三.配置两台RS匹配规则 四.停止RS1的http服务进行测试 RS1失去工作能力&#xff0c;RS2接替RS1 基于前文的LVS-DR集群构建环境 一.下…

VITS2来袭~

论文&#xff1a;VITS2: Improving Quality and Efficiency of Single-Stage Text-to-Speech with Adversarial Learning and Architecture Design 演示&#xff1a;https://vits-2.github.io/demo/ 论文&#xff1a;https://arxiv.org/abs/2307.16430 目前仍然存在的问题: int…

使用GUI Guider工具开发嵌入式GUI应用(6)-切换多screen换场景

使用GUI Guider工具开发嵌入式GUI应用&#xff08;6&#xff09;-切换多screen换场景 本节将展示使用GUI Guider实现切换显示页面功能。 这里设计的用例是&#xff1a; 创建3张页面&#xff0c;screen_0,screen_1和screen_2。分别在每个页面上中放置一个Label&#xff08;最…

C++ STL容器适配器(详解)

STL容器适配器 什么是适配器&#xff0c;C STL容器适配器详解 在详解什么是容器适配器之前&#xff0c;初学者首先要理解适配器的含义。 其实&#xff0c;容器适配器中的“适配器”&#xff0c;和生活中常见的电源适配器中“适配器”的含义非常接近。我们知道&#xff0c;无…