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

【位运算】速算密钥:位运算探秘

文章目录

  • 前言
  • 例题
    • 一、判定字符是否唯一
    • 二、丢失的数字
    • 三、两整数之和
    • 四、只出现⼀次的数字 II
    • 五、消失的两个数字
  • 结语


在这里插入图片描述

前言

什么是位运算算法呢?

位运算算法是以位运算为核心操作,设计用来高效解决特定问题的一系列计算步骤集合。它巧妙利用位运算直接对二进制位操作的特性,构建独特的逻辑流程,从而实现比常规算法更优的时间复杂度或空间复杂度。​
例如在判断一个数是否为 2 的幂次方的问题上,常规思路可能是不断除以 2 并检查余数。但位运算算法则利用二进制特性:一个数若是 2 的幂次方,其在二进制表示下只有一位是 1,其余全为 0。这种位运算算法避免了循环除法操作,极大提升了运算效率。与普通位运算不同,位运算算法不是孤立的单个操作,而是一系列位运算操作的有机组合,根据问题特性精心编排,以达成复杂问题的高效求解,在数据压缩、加密解密、图形处理等诸多对性能敏感的领域发挥着关键作用。

位运算都有哪几种呢?

按位与(&)
对两个操作数对应的二进制位进行逐位比较,只有当两个对应位都为 1 时,结果位才为 1,否则为 0。

示例代码:

public class BitwiseAndExample {public static void main(String[] args) {int a = 5; // 二进制: 0101int b = 3; // 二进制: 0011int result = a & b; // 二进制结果: 0001,十进制为 1System.out.println(result);}

按位或(|)
对两个操作数对应的二进制位进行逐位比较,只要两个对应位中有一个为 1,结果位就为 1,只有当两个对应位都为 0 时,结果位才为 0。

示例代码:

public class BitwiseOrExample {public static void main(String[] args) {int a = 5; // 二进制: 0101int b = 3; // 二进制: 0011int result = a | b; // 二进制结果: 0111,十进制为 7System.out.println(result);}
}

按位异或(^)
对两个操作数对应的二进制位进行逐位比较,当两个对应位不同时,结果位为 1,相同时结果位为 0。

示例代码:

public class BitwiseXorExample {public static void main(String[] args) {int a = 5; // 二进制: 0101int b = 3; // 二进制: 0011int result = a ^ b; // 二进制结果: 0110,十进制为 6System.out.println(result);}
}

按位取反(~)
对操作数的每个二进制位进行取反操作,即 1 变为 0,0 变为 1。

示例代码:

public class BitwiseNotExample {public static void main(String[] args) {int a = 5; // 二进制: 0101int result = ~a; // 结果为 -6System.out.println(result);}
}

左移(<<)
将操作数的二进制位向左移动指定的位数,右边空出的位用 0 填充。左移 n 位相当于将原数乘以 2 的 n 次方。

示例代码:

public class LeftShiftExample {public static void main(String[] args) {int a = 5; // 二进制: 0101int result = a << 2; // 二进制结果: 010100,十进制为 20System.out.println(result);}
}

右移(>>)
将操作数的二进制位向右移动指定的位数,左边空出的位根据原数的符号位进行填充(正数补 0,负数补 1)。右移 n 位相当于将原数除以 2 的 n 次方并向下取整。

代码示例:

public class RightShiftExample {public static void main(String[] args) {int a = 5; // 二进制: 0101int result = a >> 1; // 二进制结果: 0010,十进制为 2System.out.println(result);}
}

接下来,本篇文章将通过几道位运算的例题来详细展开位运算这一算法!

例题

一、判定字符是否唯一

  1. 题目链接:判定字符是否唯一
  2. 题目描述:

实现⼀个算法,确定⼀个字符串 s 的所有字符是否全都不同。
示例 1:
输⼊: s = “leetcode”
输出: false
示例 2:
输⼊: s = “abc”
输出: true
限制:0 <= len(s) <= 100
s[i]仅包含小写字目
如果你不使⽤额外的数据结构,会很加分。

  1. 解法(位图的思想):

算法思路:
利⽤「位图」的思想,每⼀个「比特位」代表⼀个「字符,⼀个 int 类型的变量的 32 位⾜够 表示所有的小写字母。比特位里面如果是 0 ,表⽰这个字符没有出现过。比特位里面的值是 1 , 表⽰该字符出现过。
那么我们就可以用⼀个「整数」来充当「哈希表」。

  1. 代码示例:
  public boolean isUnique(String astr) {//利用鸽巢原理来进行优化if(astr.length()>26) return false;int bitMap =0;for(int i = 0 ;i<astr.length();i++){int x = astr.charAt(i)-'a';if(((bitMap>>x)&1)==1) return false;bitMap = (1<<x)|bitMap;}return true;}

二、丢失的数字

  1. 题目链接:丢失的数字
  2. 题目描述:

给定⼀个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。
示例 1:
输入:nums = [3,0,1]
输出:2
解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没 有出现在 nums 中。
示例 2:
输入:nums = [0,1]
输出:2
解释:n = 2,因为有 2 个数字,所以所有的数字都在范围 [0,2] 内。2 是丢失的数字,因为它没 有出现在 nums 中。
示例 3:
输⼊:nums = [9,6,4,2,3,5,7,0,1]
输出:8
解释:n = 9,因为有 9 个数字,所以所有的数字都在范围 [0,9] 内。8 是丢失的数字,因为它没 有出现在 nums 中。
示例 4:
输⼊:nums = [0]
输出:1
解释:n = 1,因为有 1 个数字,所以所有的数字都在范围 [0,1] 内。1 是丢失的数字,因为它没 有出现在 nums 中。
题示:n == nums.length
1 <= n <= 10^4
0 <= nums[i] <= n
nums 中的所有数字都 独⼀⽆二
进阶:你能否实现线性时间复杂度、仅使用额外常数空间的算法解决此问题?

  1. 解法(位运算)
    算法思路:
    设数组的大小为 n ,那么缺失之前的数就是 [0, n] ,数组中是在 [0, n] 中缺失⼀个数形成 的序列。 如果我们把数组中的所有数,以及 [0, n] 中的所有数全部「异或」在⼀起,那么根据「异或」 运算的「消消乐」规律,最终的异或结果应该就是缺失的数

  2. 代码示例:

		//法一:哈希表 大家可以自行尝试>  public int missingNumber1(int[] nums) {int n =nums.length,ret = 0;int[] hash = new int[n+1];for(int i = 0;i<nums.length;i++){hash[nums[i]]++;}for(int i = 0;i<hash.length;i++){if(hash[i]==0)ret = i;}return ret;}//法二 :位运算public int missingNumber(int[] nums) {int ret = 0;for(int x :nums) ret ^= x;for(int i = 0;i<nums.length;i++) ret ^= i;return ret;}

三、两整数之和

  1. 题目链接: 两整数之和
  2. 题目描述:

给你两个整数 a 和 b ,不使⽤ 运算符 + 和 - ,计算并返回两整数之和。
示例 1:
输入:a = 1, b = 2
输出:3
示例 2:
输入:a = 2, b = 3
输出:5
提示:
-1000 <= a, b <= 1000

  1. 解法(位运算):
    算法思路:
    ◦ 异或 ^ 运算本质是「无进位加法」;
    ◦ 按位与 & 操作能够得到「进位」;
    ◦ 然后⼀直循环进行,直到「进位」变成 0 为止。

4.代码示例:

  public int getSum(int a, int b) {while (b != 0) {int x = a ^ b; // 先算出⽆进位相加的结果int carry = (a & b) << 1; // 计算进位a = x;b = carry;}return a;}

四、只出现⼀次的数字 II

  1. 题目链接:只出现一次的数字||
  2. 题目描述:

给你⼀个整数数组 nums ,除某个元素仅出现 ⼀次外,其余每个元素都恰出现三次 。请你找出并返 回那个只出现了⼀次的元素。 你必须设计并实现线性时间复杂度的算法且不使用额外空间来解决此问题。
示例 1:
输⼊:nums = [2,2,3,2]
输出:3
示例 2: 输入:nums = [0,1,0,1,0,1,99]
输出:99
提示:1 <= nums.length <= 3 * 104
-231 <= nums[i] <= 231 - 1
nums 中,除某个元素仅出现⼀次 外,其余每个元素都恰出现 三次

  1. 解法(比特位计数):

算法思路: 设要找的数位 ret 。 由于整个数组中,需要找的元素只出现了「⼀次」,其余的数都出现的「三次」,因此我们可以根据所有数的「某⼀个比特位」的总和 %3 的结果,快速定位到 ret 的「⼀个比特位上」的值是 0 还是 1 。 这样,我们通过 ret 的每⼀个比特位上的值,就可以将 ret 给还原出来。

  1. 代码示例:
  public int singleNumber(int[] nums) {int ret = 0;for (int i = 0; i < 32; i++) // 依次修改 ret 中的每⼀个⽐特位{int sum = 0;for (int x : nums) // 统计 nums 中所有的数的第 i 位的和if (((x >> i) & 1) == 1)sum++;sum %= 3;if (sum == 1) ret |= 1 << i;}return ret;}

五、消失的两个数字

  1. 题目链接:消失的两个数字
  2. 题目描述:

给定⼀个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只⽤ O(1) 的 空间找到它们吗?以任意顺序返回这两个数字均可。
示例 1:
输⼊: [1]
输出: [2,3]
示例 2:
输⼊: [2,3]
输出: [1,4]
提示:
nums.length <= 30000

  1. 解法(位运算):
    算法思路:
    和上述中消失一个数字中题解法一样,首先我们需要将该数组中的所有元素与连续情况下的数组同时异或,经过此操作后,只剩下消失的两个数字的异或,此时我们通过对找出得到结果的比特位为一,即找出两个数比特位不同的那一位,在之后,将所有的数按照位置不同,分为两类异或即可得到a,b值。

  2. 代码示例

 public int[] missingTwo2(int[] nums) {// 1. 先把所有的数异或在⼀起int tmp = 0;for (int x : nums) tmp ^= x;for (int i = 1; i <= nums.length + 2; i++) tmp ^= i;// 2. 找出 a,b 两个数⽐特位不同的那⼀位int diff = 0;while (true) {if (((tmp >> diff) & 1) == 1) break;else diff++;}// 3. 将所有的数按照 diff 位不同,分两类异或int[] ret = new int[2];for (int x : nums)if (((x >> diff) & 1) == 1) ret[1] ^= x;else ret[0] ^= x;for (int i = 1; i <= nums.length + 2; i++)if (((i >> diff) & 1) == 1) ret[1] ^= i;else ret[0] ^= i;return ret;}

结语

本文到这里就结束了,主要介绍了位运算法则,并通过几道例题更加深入了解位运算相关题目的应用。希望能够对你有帮助。

以上就是本文全部内容,感谢各位能够看到最后,创作不易,希望大家多多支持!

最后,大家再见!祝好!我们下期见!

相关文章:

【位运算】速算密钥:位运算探秘

文章目录 前言例题一、判定字符是否唯一二、丢失的数字三、两整数之和四、只出现⼀次的数字 II五、消失的两个数字 结语 前言 什么是位运算算法呢&#xff1f; 位运算算法是以位运算为核心操作&#xff0c;设计用来高效解决特定问题的一系列计算步骤集合。它巧妙利用位运算直接…...

STM32G070CBT6读写FLASH中的数据

向FLASH中写入数据函数 /*函数说明&#xff1a;向FLASH中写数据形参&#xff1a;addr-要写入数据的起始地址 data-准备写入数据 len-数据大小返回值&#xff1a;1-成功&#xff0c;0-失败 */ uint8_t FlashWriteData(uint64_t addr,uint8_t data[],size_t len) {uint32_t Fir…...

算法刷题记录——LeetCode篇(4) [第301~400题](持续更新)

(优先整理热门100及面试150&#xff0c;不定期持续更新&#xff0c;欢迎关注) 322. 零钱兑换 给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 amount &#xff0c;表示总金额。 计算并返回可以凑成总金额所需的最少的硬币个数。如果没有任何…...

目标检测任务,如何区分两个相近似的目标

首先&#xff0c;要了解清楚检测的场景下&#xff0c;肉眼能否区分出目标的差异性。 如果可以区分&#xff0c;那观察数据周围背景的差异是否较大&#xff0c;可以先通过添加样本来提升模型的检测精度。添加样本时一定要注意&#xff0c;样本标注的准确性&#xff0c;样本的丰…...

中国在 AI 上超越美国,需要另辟蹊径

在过去的几年里&#xff0c;以大型语言模型&#xff08;LLM&#xff09;为核心的人工智能浪潮席卷全球。美国凭借其雄厚的科研基础、顶尖的技术公司以及掌握着关键硬件资源&#xff0c;牢牢占据了这一领域的领先地位。与此同时&#xff0c;中国在AI领域的进步虽然迅速&#xff…...

【实习经历Two:参与开源项目,学习并应用Git】

前端参与开源项目中使用过的git 1.参与开源项目&#xff08;必备技能——git) 参与开源项目首先需要进入自己想参加的项目页面 点击右边的Fork即可复制到自己的仓库 像个人开发时常用的add、commit和push等命令就不过多介绍了&#xff0c;在这里主要是想记录一下自己作为从未…...

AD绘图基本操作

一、基本操作 注意&#xff1a;快捷键都要在英文模式下才能生效 1、移动 按住鼠标右键移动 2、切换桌面栅格距离 G 3、英寸和毫米 尺寸切换 Q 4、元件在3D模式下的移动 3D视角鼠标左键只起到选择元器件并移动之的功能&#xff0c; 单纯鼠标右键只能平移桌面 shift鼠…...

6k ± 1 规则

6k 1 规则 是基于对质数分布规律的观察和数学证明得出的。它指出&#xff0c;除了 2 和 3 之外&#xff0c;所有质数都可以表示为 6k 1 的形式&#xff0c;其中 k 是正整数。以下是详细的证明过程&#xff1a; 1. 质数的基本性质 质数是指大于 1 的自然数&#xff0c;且只能…...

AcWing 5960:输出前k大的数 ← 小根堆

【题目来源】 https://www.acwing.com/problem/content/5963/ 【题目描述】 给定一个长度为 n 的数组 a1,a2,…,an&#xff0c;统计前 k 大的数并且把这 k 个数从大到小输出。 【输入格式】 第一行包含整数 n。 第二行包含 n 个整数 a1,a2,…,an。 第三行包含整数 k。​​​​…...

V2X验证

1. 标准和规范验证 欧洲对 DSRC 和 V2X 系统有一系列的标准和规范,主要由 ETSI (European Telecommunications Standards Institute) 和 IEEE 等组织制定。验证通常包括以下标准和规范: ETSI EN 302 571:这是DSRC在欧洲的主要标准,规定了DSRC系统的技术要求和操作条件。ET…...

创建表空间和表

创建表 1.业务背景 在城市的住宅小区和商业区域中&#xff0c;需要对业主的用水情况及费用缴纳进行有效管理。业主类型涵盖普通居民、商业用户等不同类别&#xff08;业主类型表&#xff09;&#xff0c;每种类型对应不同的水价标准&#xff08;价格表&#xff09;。区域表记…...

dfs(十二)21. 合并两个有序链表 递归解决

21. 合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]示例 2&#xff1a; 输入&#xff1a;l1 [], l2 [] …...

51单片机指令系统入门

目录 基本概念讲解 一、机器指令​ 二、汇编指令​ &#xff08;一&#xff09;汇编指令的一般格式 &#xff08;二&#xff09;按字节数分类的指令 三、高级指令 总结​ 基本概念讲解 指令是计算机&#xff08;或单片机&#xff09;中 CPU 能够识别并执行的基本操作命令…...

安全无事故连续天数计算,python 时间工具的高效利用

安全天数计算&#xff0c;数据系统时间直取&#xff0c;安全标准高效便捷好用。 笔记模板由python脚本于2025-03-17 23:50:52创建&#xff0c;本篇笔记适合对python时间工具有研究欲的coder翻阅。 【学习的细节是欢悦的历程】 博客的核心价值&#xff1a;在于输出思考与经验&am…...

如何玩DeepSeek!15分钟快速创建GIS动态数据可视化仪表盘

DeepSeek最近火遍全球&#xff0c;大家用的都用的不亦乐乎。国外呢&#xff1f;当然也是&#xff0c;最近一上YouTube、X等都是deepseek的推送。 今天介绍一下&#xff0c;我在YouTube上看到的GIS行业与DeepSeek结合的一个案例&#xff1a; 快速轻松构建交互式地图仪表盘&…...

课上测试:MIRACL共享库使用测试

MIRACL(MultiprecisionIntegerandRationalArithmeticC/cLibrary)是著名的密码算法库&#xff0c;设法去官网下载安装MIRACL&#xff0c;提交安装过程截图或过程文本&#xff08;3分&#xff09;. 去github官网下载.zip文件 使用如下命令进行解压 unzip -j -aa -L MIRACL-mast…...

网络编程知识预备阶段

1. OSI七层模型 OSI&#xff08;Open System Interconnect&#xff09;七层模型是一种将计算机网络通信协议划分为七个不同层次的标准化框架。每一层都负责不同的功能&#xff0c;从物理连接到应用程序的处理。这种模型有助于不同的系统之间进行通信时&#xff0c;更好地理解和…...

Echo服务详解与实现

各类资料学习下载合集 ​​https://pan.quark.cn/s/8c91ccb5a474​​ 在网络编程中,Echo服务是一个非常基础且重要的服务,它的功能是接收客户端发送的数据,并将相同的数据返回给客户端。本文将详细介绍如何使用Python实现一个简单的Echo服务,并提供完整的代码实例及运行结…...

STM32微控制器_03_GPIO原理与应用

核心内容 STM32 GPIO基本原理&#xff08;熟悉&#xff09;GPIO输出功能HAL库编程实现的应用&#xff08;重点&#xff09;GPIO输入功能HAL库编程实现的应用&#xff08;重点&#xff09; 一.STM32 GPIO基本原理 1.GPIO简介 STM32的GPIO相当于STM32的四肢&#xff0c;一个S…...

零拷贝分析

kafka 零拷贝 请求 - 网口 - socket - 用户态 - 内核缓存区 - 内核态&#xff08;磁盘信息&#xff09; 磁盘 - 内核缓存区 - 用户缓存区 - 网络缓存区 零拷贝&#xff08;Zero-Copy&#xff09; 是一种高效的数据传输技术&#xff0c;旨在减少数据在内存中的拷贝次数&#x…...

爬虫逆向:详细讲述Android底层原理及机制

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Android系统架构1.1 Linux内核层1.2 硬件抽象层(HAL)1.3 系统运行库层1.4 应用框架层1.5 应用层二、Android启动过程三、进程与线程管理四、内存管理机制五、Binder机制六、安全机制七、电源管理机制八、Android …...

电容器基础观念

Take-away: 电容器容值&#xff0c;和「导体的几何形状」&#xff0c;「周围的介电材料」相关。电力线起于正电荷&#xff0c;终止于负电荷。金属互相越靠近&#xff0c;电容越大。Maxwell电容矩阵有负号&#xff0c;SPICE电容矩阵没有负号。Maxwell电容矩阵、SPICE电容矩阵可…...

Python 视频爬取教程

文章目录 前言基本原理环境准备Python安装选择Python开发环境安装必要库 示例 1&#xff1a;爬取简单直链视频示例 2&#xff1a;爬取基于 HTML5 的视频&#xff08;以某简单视频网站为例&#xff09; 前言 以下是一个较为完整的 Python 视频爬取教程&#xff0c;包含基本原理…...

NumPy系列 - 创建矩阵

目录 前传直接创建数组就只是创建数组1. np.array()2. np.arange()3. np.ones()4. numpy.ones_like()5. np.zeros()6. numpy.zeros_like() 定义数据类型 参考资料 前传 由于&#xff0c;某人在上智能相关课程的时候&#xff0c;总想着一大堆的事情&#xff0c;统计股市涨跌&am…...

从Instagram到画廊:社交平台如何改变艺术家的展示方式

从Instagram到画廊&#xff1a;社交平台如何改变艺术家的展示方式 在数字时代&#xff0c;艺术家的展示方式正在经历一场革命。社交平台&#xff0c;尤其是Instagram&#xff0c;已经成为艺术家展示作品、与观众互动和建立品牌的重要渠道。本文将探讨社交平台如何改变艺术家的…...

谈谈 TypeScript 中的联合类型(union types)和交叉类型(intersection types),它们的应用场景是什么?

一、联合类型&#xff08;Union Types&#xff09; 核心概念 使用管道符 | 表示多选一关系&#xff0c;典型场景&#xff1a;处理可能存在多种类型的变量 // 基础示例&#xff1a;处理数值型ID&#xff08;number&#xff09;或哈希型ID&#xff08;string&#xff09; type…...

华为OD机试 - 最长的完全交替连续方波信号(Java 2023 B卷 200分)

题目描述 给定一串方波信号,要求找出其中最长的完全连续交替方波信号并输出。如果有多个相同长度的交替方波信号,输出任意一个即可。方波信号的高位用1标识,低位用0标识。 说明: 一个完整的信号一定以0开始并以0结尾,即010是一个完整的信号,但101,1010,0101不是。输入的…...

✎ 一次有趣的经历

&#x1f4c6;2025年3月17日 | 周一 | ☀️晴 &#x1f4cd;今天路过学院楼7&#xff0c;见到了满园盛开的花&#x1f33a;&#xff0c;心情瞬间明朗&#xff01; &#x1f4cc;希望接下来的日子也能像这些花一样&#xff0c;充满活力&#x1f525;&#xff01; &#x1…...

【Spring】第二弹:通过反射机制初步理解 IoC

一、Java 反射机制 Java反射机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用它的任意方法和属性&#xff1b;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机…...

快!快!快!NDPP时延测试数据公布!

在全方位认识NDPP第3期《NDPP在金融场景的应用》中&#xff0c;我们重点介绍了NDPP的典型应用场景行情解码硬件加速和策略计算加速&#xff0c;并帮助某百亿私募用户基于NDPP实现期货业务加速的案例。 近期&#xff0c;中科驭数凭借低时延产品荣获信创“大比武”行业融合赛道三…...