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

关于位运算的巧妙性:小乖,你真的明白吗?

一.位运算的概念

什么是位运算?

程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行操作。

位运算就是直接操作二进制数,那么有哪些种类的位运算呢?

常见的运算符有与(&)、或(|)、异或(^)、取反(~)、左移(<<)、右移(>>是带符号右移 >>>无符号右移动)。下面来细看看每一种位运算的规则。

  1. &操作符:运算规则:将两个数字的二进制位进行按位与操作,即当两个数字的某位二进制数中同时为1结果才为1,否则是0 0&0=0, 0&1=0, 1&1=1

例子:

  1. 位运算 | (或)

规则:二进制对应位两两进行逻辑或运算(对应位中有一 个为1则为1) 即0|0=0,0|1=1,1|1=1

3.位运算 ^ (异或)

规则:二进制对应位两两进行逻辑XOR (异或) 的运算(当对应位的值不同时为 1, 否则为 0)即0^0=0, 0^1=1, 1^1=0

4.

按位取反~

规则:二进制的0变成1,1变成0。

5.

左移运算<<:左移后右边位补 0

右移运算>>:右移后左边位补原最左位值(可能是0,可能是1)

右移运算>>>:右移后左边位补 0

关于位运算的规则,我们再进行详细的讲述:关于左移,无论对于正数还是负数,结果都是在原来数值的基础上进行乘2操作,但是对于右移符号,这其中就有说法了:>>>,对于无符号右移:它的运算规则是将原有数字右移,在左边补0,也就是说,如果原有的数字是负数,通过无符号右移会变成正数,对于正数则是简单的除2的效果,对于>>右移符号,则是无论对于正数还是负数,达到的效果都是除2

二.关于位运算的常见题目

  1. 交换两个数

利用位运算将数个数值进行交换
a=a^b;//a=a^b
b=a^b;//b=(a^b)^b=a^0=a
a=a^b;//a=(a^b)^(a^b^b)=0^b=0
  1. 判断奇偶数

给定一个数值,判断这个数字是奇数还是偶数
if(n & 1 == 1){// n 是个奇数。
}
  1. 不用加减乘除做加法

牛客链接:https://www.nowcoder.com/practice/e7e0d226f1e84ba7ab8b28efc6e1aebc?tpId=8&&tqId=11065&rp=1&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking

实现思路:关于实现加法运算而不使用加减乘除运算,我们则可以选择调用相关的位运算进行求解

①按位异或(^):可以实现无进位的加法运算

比如: 1 ^ 1 = 0 ---> 1 + 1 = 0 (当前位值为0,进一位)

1 ^ 0 = 1 ---> 1 + 0 = 1 (当前位值为1)

0 ^ 0 = 0 ---> 0 + 0 = 0 (当前位值为0

②按位与(&)然后左移一位:能够表示进位情况:

比如: 1 & 1 = 1 ---> 1 + 1 = 0 (当前位的值进一位)

1 & 0 = 0 ---> 1 + 0 = 1 (当前位的值不进位)

0 & 0 = 0 ---> 0 + 0 = 0 (当前位的值不进位)

两个数相加:对应二进制位相加的结果 + 进位的结果

比如:3 + 2 --> 0011 + 0010 --> 0011 ^ 0010 + ((0011 & 0010) << 1)

---> (0011 ^ 0010) ^ ((0011 & 0010) << 1), 当进位之后的结果为0时,相加结束

public int addAB(int A, int B) {
// write code here
if(B==0){
return A;
}
int sum=0;
int carray=0;
while(B!=0){
sum=A^B;
carray=(A&B)<<1;
A=sum;
B=carray;
}
return A;
}
  1. 求出现一次的数字①

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

实现思路:

根据异或运算的特性,我们能够理解的是:任何数字异或自身,结果都是0,所以对于所有成对出现的数字而言,我们将其全部异或一遍,其结果是0,再将唯一出现的数字再次异或,最后的结果也就是那个唯一出现的数字。

我们给出code:

class Solution {public int singleNumber(int[] nums) {int value=0;for(int i=0;i<nums.length;i++){value^=nums[i];}return value;}
}
  1. 求出现一次的数字②

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

LeetCode链接:https://leetcode.cn/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/solution/jian-zhi-offer-56-i-shu-zu-zhong-shu-zi-tykom/

与①有所不同的是,这次题目的给出的条件是有两个不同的数字,让我们分别找出这两个数字,既然仍然是出现多组出现两次的数字,那么我们的实现大思路仍然保持不变,就是通过不断异或来排除出现两次的数字,那么这时候便引出了问题的关键,异或之后剩下的结果是两个数字异或之后的结果,那么我们如何在结果中将这两个数字分别拿出来呢?这里我们选择的策略是区分两个数字中不同的一位,具体实现思路如下:首先将所有数字进行异或,将最后生成的结果与m(m=1)进行异或,目的是找出异或结果中为1的一位(因为两个不同的数字必然有一位不同,异或结果是1),我们利用这个辨识特点,分别对数组进行分组异或,最后的两个数字就是异或的结果,具体code如下:

class Solution {public int[] singleNumbers(int[] nums) {//因为相同的数字异或为0,任何数字与0异或结果是其本身。//所以遍历异或整个数组最后得到的结果就是两个只出现一次的数字异或的结果:即 z = x ^ yint z = 0;  for(int i : nums) z ^= i;//我们根据异或的性质可以知道:z中至少有一位是1,否则x与y就是相等的。//我们通过一个辅助变量m来保存z中哪一位为1.(可能有多个位都为1,我们找到最低位的1即可)。//举个例子:z = 10 ^ 2 = 1010 ^ 0010 = 1000,第四位为1.//我们将m初始化为1,如果(z & m)的结果等于0说明z的最低为是0//我们每次将m左移一位然后跟z做与操作,直到结果不为0.//此时m应该等于1000,同z一样,第四位为1.int m = 1;while((z & m) == 0) m <<= 1;//我们遍历数组,将每个数跟m进行与操作,结果为0的作为一组,结果不为0的作为一组//例如对于数组:[1,2,10,4,1,4,3,3],我们把每个数字跟1000做与操作,可以分为下面两组://nums1存放结果为0的: [1, 2, 4, 1, 4, 3, 3]//nums2存放结果不为0的: [10] (碰巧nums2中只有一个10,如果原数组中的数字再大一些就不会这样了)//此时我们发现问题已经退化为数组中有一个数字只出现了一次//分别对nums1和nums2遍历异或就能得到我们预期的x和yint x = 0, y = 0;for(int i : nums) {//这里我们是通过if...else将nums分为了两组,一边遍历一遍异或。//跟我们创建俩数组nums1和nums2原理是一样的。if((i & m) == 0) x ^= i;else y ^= i;}return new int[]{x, y};}
}

实现思路:

6.求出现一次的数字③

在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。

LeetCode链接:https://leetcode.cn/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-ii-lcof/

实现思路:相对于出现两次的数字,能够利用异或的规律解决问题,出现三次的数字显得毫无规律可言,那么我们又该如何解决出现三次的数字问题呢?我们可以观察其每一位数字的规律:对于每一位数字而言,既然是出现三次,那么则可以对数组中的每一位数字的32个二进制位进行遍历,记录每一位的结果,至于最后返回的数字,我们可以通过res(res=0)和数组中的每一位进行%3然后进行或操作,然后将res左移,让二进制中的每一位回到原来的位置即可,code如下:

class Solution {public int singleNumber(int[] nums) {int[] counts = new int[32];for(int num : nums) {for(int j = 0; j < 32; j++) {counts[j] += num & 1;num >>>= 1;}}int res = 0, m = 3;for(int i = 0; i < 32; i++) {res <<= 1;res |= counts[31 - i] % m;}return res;}
}

7.n皇后问题的位运算优化

notes:需要注意的是,利用位运算解决n皇后问题的暴力递归问题只是对效率问题进行常数级别的优化:

limit:是位数限制,对于行列数为N的棋盘,limit的限制是:对于前N个二进制位数均为1,对于N行列的棋盘而言,前N个二进制位代表棋盘的每一行(第一个二进制位代表第一行,第二个代表第二行........)

①col:对于每次摆放个皇后,就将这个二进制位置变为1,表示这个二进制位不能摆放皇后了

②leftLim:左斜线限制,如果leftLim为1,代表对于当前行来说,这个位置不能摆放皇后了。

③RightLim:右斜线限制,如果RightLim为1,同样对于当前行来说,这个位置不能摆放皇后了。

④limit==col:代表col前N个二进制位都是1,表示N个皇后都已经摆放好了,游戏结束,退出递归

⑤limit&(~(col|leftLim|rightLim)):pos是在每一行中能选择的列

⑥ mostRight=pos&(~pos+1):取出最右边的一位

⑦ pos-=mostRight:将最右边的位置从可选择的位数中去除,使当前行不能放置皇后

⑧while(pos!=0) 循环当前行中能选择的位置

⑨res+= process2(limit,col|mostRight,(leftLim|mostRight)<<1, (rightLim|mostRight)>>>1):循环下一层

code如下:

public static int process2(int limit,int col,int leftLim,int rightLim){//递归出口if(limit==col){return 1;}//计算能放的位置:int pos= limit&(~(col|leftLim|rightLim));int mostRight=0;int res=0;//检验是否能递归while(pos!=0){//找最右的位置mostRight=pos&(~pos+1);pos-=mostRight;res+=  process2(limit,col|mostRight,(leftLim|mostRight)<<1, (rightLim|mostRight)>>>1);}return res;

相关文章:

关于位运算的巧妙性:小乖,你真的明白吗?

一.位运算的概念什么是位运算&#xff1f;程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行操作。位运算就是直接操作二进制数&#xff0c;那么有哪些种类的位运算呢&#xff1f;常见的运算符有与(&)、或(|)、异或(^)、…...

【Android车载系列】第5章 AOSP开发环境配置

1 硬件支持 建议空闲内存16G以上&#xff0c;同时硬盘400G以上 内存不够可以使用 Linux 的交换分区2 VMware Workstation安装 https://download3.vmware.com/software/wkst/file/VMware-workstation-full-16.1.1-17801498.exe2.1 Ubuntu镜像 http://mirrors.aliyun.com/ubun…...

个人时间管理网站—Git项目管理

&#x1f31f;所属专栏&#xff1a;献给榕榕&#x1f414;作者简介&#xff1a;rchjr——五带信管菜只因一枚&#x1f62e;前言&#xff1a;该专栏系为女友准备的&#xff0c;里面会不定时发一些讨好她的技术作品&#xff0c;感兴趣的小伙伴可以关注一下~&#x1f449;文章简介…...

2023最新ChatGPT整理的40道Java高级面试题

2023 年最火的就是 ChatGPT 了,很多同事使用他完成一些代码上的智能提示,也有人使用它发了财《「用ChatGPT年入百万!」各博主发布生财之道,网友:答辩搬运工》、《“躺着就能赚大钱”?ChatGPT火了,有人早就动起坏脑筋》等。 最近我也使用 ChatGPT 写技术文章了,比如:《…...

单机分布式一体化是什么?真的是数据库的未来吗,OceanBase或将开启新的里程碑

一. 数据 我们先说说数据这个东西&#xff0c;这段时间的ChatGPT在全世界的爆火说明了一件事&#xff0c;数据是有用的&#xff0c;并且大量的数据如果有一个合适的LLM大规模语言模型训练之后&#xff0c;可以很高程度的完成很多意想不到的事情。 我们大多数的时候的注意力只…...

100天精通Python丨基础知识篇 —— 03、Python基础知识扫盲(第一个Python程序,13个小知识点)

文章目录&#x1f41c; 1、Python 初体验Pycharm 第一个程序交互式编程第一个程序&#x1f41e; 2、Python 引号&#x1f414; 3、Python 注释&#x1f985; 4、Python 保留字符&#x1f42f; 5、Python 行和缩进&#x1f428; 6、Python 空行&#x1f439; 7、Python 输出&…...

springboot逍遥大药房管理系统

084-springboot逍遥大药房管理系统演示录像开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&a…...

ZYNQ中的GPIO与AXI GPIO

GPIO GPIO—一种外设&#xff0c;对器件进行观测和控制MIO—将来自PS外设和静态存储器接口的访问多路复用到PS引脚上处理器控制外设的方法—通过一组寄存器包括状态寄存器和控制寄存器&#xff0c;这些寄存器都是有地址的&#xff0c;通过这些寄存器的读写进行外设的控制sessi…...

接口导入功能

1.接口api export function import(param) { return fetch({ url: XXX.import, method: POST, headers: { Content-Type: multipart/form-data; }, data: param }) } 2.页面vue 和 js逻辑 <el-button :loading"disable&qu…...

网络安全知识点总结 期末总结

1、信息安全从总体上可以分成5个层次&#xff0c;密码技术 是信息安全中研究的关键点。 2、握手协议 用于客户机与服务器建立起安全连接之前交换一系列信息的安全信道。 3、仅设立防火墙系统&#xff0c;而没有 安全策略 &#xff0c;防火墙就形同虚设。 4、应用代理防火墙 …...

linux挂载远程目录

服务端操作 # 1、安装NFS程序 yum -y install nfs* rpcbind,在centos6以前自带的yum源中为portmap。 使用yum安装nfs时会下载依赖&#xff0c;因此只要下载nfs即可&#xff0c;无需再下载rpcbind. # 2、查看是否安装了nfs与rpcbind rpm -qa | grep nfs rpm -qa | grep rpc…...

ChatGPT—初识

ChatGPT初识 由于ChatGPT 注册相关的文章被平台限制了&#xff0c;所以有注册相关的问题可以私聊&#xff0c;或者可以代注册 Chat GPT是一款基于GPT模型的对话型AI模型&#xff0c;能够模拟真实的对话风格和行为方式&#xff0c;让人与AI的交互变得更加自然顺畅。下面将从Chat…...

【ArcGIS Pro二次开发】(18):地理处理工具类【Geoprocessing】补遗

ArcGIS Pro SDK 3.0中的Geoprocessing类是用于执行地理处理工具的核心类。地理处理工具是用于执行空间分析、数据转换、数据管理等任务的工具集&#xff0c;包括常见的空间分析工具、栅格处理工具、矢量处理工具、地图制图工具等。 之前有简单记录了下Geoprocessing工具的用法…...

国产芯片方案——红外测温体温计方案

红外测温体温计采用了热电堆式&#xff0c;利用塞贝克效应&#xff0c;将收集到的红外线光信号转化为电信号&#xff0c;再经过放大等处理&#xff0c;按内部的算法校正后再显示屏幕上输出具体温度值&#xff0c;能快速准确地测量人体体温。红外测温体温计广泛应用于医疗卫生、…...

详解ChatGPT的免费总结插件Glarity

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,科大讯飞比赛第三名,CCF比赛第四名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…...

RK3588平台开发系列讲解(NPU篇)NPU调试方法

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、日志等级二、NPU 支持查询设置项沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇我们一起来看一下NPU的调试方法。 一、日志等级 NPU 的运行库会根据开发板上的系统环境变量输出一些日志信息或者生成…...

基于微信小程序+爬虫制作一个表情包小程序

跟朋友聊天斗图失败气急败坏的我选择直接制作一个爬虫表情包小程序&#xff0c;从源头解决问题&#xff0c;从此再也不用担心在斗图中落入下风 精彩专栏持续更新↓↓↓ 微信小程序实战开发专栏 一、API1.1 项目创建1.2 图片爬虫帮助类1.3 测试窗体1.4 接口封装二、小程序2.1 项…...

TS常用数据类型(TypeScript常用数据类型,ts常用数据类型和js常用数据类型的区别)

简述&#xff1a;TS全称TypeScript&#xff0c;是一门弱类型的语言&#xff0c;可以理解为是 JavaScript 的扩展语法&#xff0c;因此我们可以在 ts 中继续写js代码&#xff0c;且不会报错&#xff0c;而且TypeScript 又叫做静态的JavaScript&#xff0c;可称为静态类型语言&am…...

关于Numpy的特殊符号@和矩阵运算

符号之谜 在Numpy中&#xff0c;看到了符号&#xff0c;但是无论是google搜索或者baidu搜索&#xff0c;由于符号是一个特殊字符&#xff0c;所以很难检索到答案。 其实很简单&#xff0c;他就是Numpy库中的一个操作符&#xff0c;在numpy库的说明中&#xff0c;落在numpy.mat…...

动态版通讯录——“C”

各位CSDN的uu们你们好呀&#xff0c;今天&#xff0c;小雅兰的内容是动态版通讯录啦&#xff0c;其实之前&#xff0c;我就已经写过静态版的通讯录了&#xff0c;只是存在着一些问题&#xff0c;具体细节可以详细看看我的静态版通讯录&#xff0c;好了&#xff0c;话不多说&…...

SpringBoot 将PDF转成图片或World

SpringBoot 将PDF转成图片或World 准备工作Apache PDFBox将PDF转成一张图片将PDF转成多张图片将PDF转成其他文件格式总结SpringBoot 是一款非常流行的 Java Web 开发框架,可以用来构建各种 Web 应用程序。在本篇博客中,我们将介绍如何使用 SpringBoot 将 PDF 转换成图片或其他…...

JavaScript中的for in和for of的区别(js的for循环)

简述&#xff1a;js中的for循环大家都知道&#xff0c;今天来分享下for in和for of在使用时区别和注意事项&#xff0c;顺便做个笔记&#xff1b; 测试数据 //数组const arr [1, 2, 3, 4, 5]//对象const obj {name: "小李",color: ["plum", "pink&q…...

C++的各种初始化

C的各种初始化 1.默认初始化 默认初始化是指定义变量时没有指定初值时进行的初始化操作。例如int a; Sales_data myData;等等。这些变量被定义了而不是仅仅被声明&#xff08;因为没有extern关键字修饰&#xff09;&#xff0c;而且没有显式的赋予初值。特别的&#xff0c;如…...

使用Python突破某网游游戏JS加密限制,进行逆向解密,实现自动登录

兄弟们天天看基础看腻了吧 今天来分享一下如何使用Python突破某网游游戏JS加密限制&#xff0c;进行逆向解密&#xff0c;实现自动登录。 逆向目标 目标&#xff1a;某 7 网游登录主页&#xff1a;aHR0cHM6Ly93d3cuMzcuY29tLw接口&#xff1a;aHR0cHM6Ly9teS4zNy5jb20vYXBpL…...

用CSS3画了一只猫

感觉我写得技术含量不高&#xff0c;全都是用绝对定位写的&#xff0c;一定会有更好的&#xff0c;代码量更少的做法吧 <!DOCTYPE html> <html> <head><title>Cute Cat</title><style type"text/css">*{box-sizing: border-box…...

菜鸟刷题Day7

⭐作者&#xff1a;别动我的饭 ⭐专栏&#xff1a;菜鸟刷题 ⭐标语&#xff1a;悟已往之不谏&#xff0c;知来者之可追 一.整理字符串&#xff1a;1544. 整理字符串 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个由大小写英文字母组成的字符串 s 。 一个整理好的字…...

蓝桥杯刷题第二十三天

第一题&#xff1a;长草题目描述小明有一块空地&#xff0c;他将这块空地划分为 n 行m 列的小块&#xff0c;每行和每列的长度都为 1。小明选了其中的一些小块空地&#xff0c;种上了草&#xff0c;其他小块仍然保持是空地。这些草长得很快&#xff0c;每个月&#xff0c;草都会…...

进阶指针(3)——指针与数组笔试题的解析

在讲解之前我们先回顾一下&#xff0c;以下将要涉及的重要知识点&#xff1a; 1、数组名是什么&#xff1f; ①sizeof(数组名)&#xff0c;这里的数组名表示整个数组&#xff0c;计算的是整个数组的大小&#xff0c;单位是字节&#xff1b; ②&数组名&#xff0c;这里的数…...

树与二叉树的存储与遍历

文章目录一、树概念二、二叉树三、二叉树的存储与遍历一、树概念 如前面的顺序表&#xff0c;链表&#xff0c;栈和队列都是线性的数据结构&#xff0c;树是非线性的结构。树可以有n个结点&#xff0c;n>0,当n0是就表示树为空 n>0,代表树不为空&#xff0c;不为空的树&am…...

28-队列练习-LeetCode622设计循环队列

题目 设计你的循环队列实现。 循环队列是一种线性数据结构&#xff0c;其操作表现基于 FIFO&#xff08;先进先出&#xff09;原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。 循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通…...

商城网站 后台/网站seo设置是什么

我正在为我的项目准备一个酒店预订页面,但是我很难把表格弄好。我有许多输入字段,我当前的代码只是使它成为一个非常长的页面。我的预订单基本上有两部分:客户信息和房间偏好。我想把左边的客户信息和右边的房间偏好对齐。因为我计划验证表单,所以我希望它是相同的 My form cur…...

搭建动态网站的步骤/网络销售怎么学

初始化 RocksDB.loadLibrary();//加载jniRocksDB db RocksDB.open(options, db_path_not_found)//打开数据库使用 单条插入 db.put("hello".getBytes(), "world".getBytes());批量插入 try (final WriteOptions writeOpt new WriteOptions()) {for (int …...

网站地图制作视频教程/网站推广做什么

四种方法实现单元格内的自动换行&#xff1a;  1&#xff0e;输入数据随时换行 在输入数据时换行&#xff0c;AltEnter组合键即可实现。此方法可使已输入内容的单元格在光标所在处换行。  2&#xff0e;单元格区域内换行  将某个长行转成段落并在指定区域内换行。例如&am…...

烟台搭建网站建设制作/怎样做关键词排名优化

现在很多的朋友都应该见过VR全景&#xff0c;但是不知道VR全景具体是什么&#xff1f;是怎么做的&#xff1f;有什么作用&#xff1f;今天小粉就给大家说一下。VR全景是当今最新颖的宣传展示的手段&#xff0c;代表了科技的更进一步&#xff0c;随着5G的发展&#xff0c;VR全景…...

网络技术学习网站/网络营销招聘

常用的callbacks函数有EarlyStopping&#xff08;提前停止训练&#xff09; ModelCheckpoint&#xff08;保存最优模型&#xff09;CSVLogger &#xff08;保存训练过程的精度、loss等&#xff09;ReduceLROnPlateau&#xff08;当模型性能无法进一步提升时降低学习率&#xff…...

天津市网站建设 网页制作/长治网站seo

产品安装选项分为两类&#xff1a;发行区域部署选项&#xff0c;本地部署选项 1、 在主机A上安装Rational Common Licensing2、 创建发行区域&#xff0c;指定默认license服务器为A&#xff0c;默认注册服务器为B&#xff0c;默认备份注册服务器为C3、 在主机B上安装clearcase …...