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

算法 按位运算

按位与(Bitwise AND)和按位异或(Bitwise XOR)

按位与(&)

按位与是对两个数的二进制表示的每一位进行逻辑与操作。

规则:两个对应位都为1时,结果位才为1,否则为0。

示例:

5 & 35 的二进制:0101
3 的二进制:0011
-----------
按位与:0001 (即1)

按位异或(^)

按位异或是对两个数的二进制表示的每一位进行逻辑异或操作。

规则:两个对应位不同时,结果位为1,相同时为0。

示例:

5 ^ 35 的二进制:0101
3 的二进制:0011
-----------
按位异或:0110 (即6)

特性

按位与特性:

  • x & 0 = 0
  • x & x = x
  • x & ~x = 0
  • 可用于检查奇偶性:x & 1(结果为1则是奇数,0则是偶数)

按位异或特性:

  • x ^ 0 = x
  • x ^ x = 0
  • x ^ y = y ^ x(交换律)
  • (x ^ y) ^ z = x ^ (y ^ z)(结合律)
  • 可用于交换两个变量的值(不使用临时变量):
    a ^= b;
    b ^= a;
    a ^= b;
    

应用场景

按位与常见用途:

  1. 掩码操作(提取特定位)
  2. 判断奇偶性
  3. 权限系统中检查权限

按位异或常见用途:

  1. 交换两个变量的值
  2. 加密算法
  3. 查找唯一出现一次的数字(其他数字都出现两次)
  4. 图形学中的颜色混合

这两种位操作在底层编程、算法优化和嵌入式系统中经常使用。

完整的按位运算

除了按位与(AND)和按位异或(XOR)外,还有以下几种常见的按位运算:

1. 按位或(Bitwise OR) |

对两个数的二进制表示的每一位进行逻辑或操作。

规则:两个对应位中只要有一个为1,结果位就为1。

示例:

5 | 35 的二进制:0101
3 的二进制:0011
-----------
按位或:0111 (即7)

特性

  • x | 0 = x
  • x | x = x
  • x | ~x = ~0(全1)
  • 常用于设置特定位为1

2. 按位非(Bitwise NOT) ~

对一个数的二进制表示的每一位进行取反操作(一元运算符)。

规则:0变1,1变0。

示例:

~55 的二进制:0101
-----------
按位非:1010 (在4位表示中为-6,具体取决于数据类型长度)

注意:结果取决于数值的位数和表示方式(补码表示法)。

3. 左移(Left Shift) <<

将二进制数向左移动指定位数,右侧补0。

效果:相当于乘以2的n次方(无溢出时)。

示例:

5 << 25 的二进制:0101
左移2位:010100 (即20)

4. 右移(Right Shift) >>

将二进制数向右移动指定位数,左侧补符号位(算术右移)或补0(逻辑右移,取决于语言)。

效果:相当于除以2的n次方(向下取整)。

示例:

5 >> 15 的二进制:0101
右移1位:0010 (即2)

5. 无符号右移(Zero-fill Right Shift) >>>(某些语言如Java、JavaScript)

将二进制数向右移动指定位数,左侧总是补0。

示例:

-5 >>> 1 (在32位系统中)-5 的二进制:11111111111111111111111111111011
无符号右移1位:01111111111111111111111111111101 (一个大正数)

复合赋值运算符

所有位运算符都有对应的复合赋值形式:

  • &= (按位与赋值)
  • |= (按位或赋值)
  • ^= (按位异或赋值)
  • <<= (左移赋值)
  • >>= (右移赋值)
  • >>>= (无符号右移赋值)

应用总结

运算符名称用途示例
&按位与掩码操作、权限检查
l按位或设置特定位
^按位异或交换值、加密、找唯一数
~按位非取反操作
<<左移快速乘以2的幂
>>右移快速除以2的幂(算术右移)
>>>无符号右移处理无符号数的右移(逻辑右移)

这些位运算在底层编程、算法优化、嵌入式系统开发、图形处理和加密算法中都有广泛应用。

Java 实现:查找唯一出现一次的数字(其他数字都出现两次)

方法思路
  1. 异或运算特性

    • 任何数和 0 异或等于它本身:x ^ 0 = x 0 在异或运算中相当于“无影响”
    • 任何数和自身异或等于 0x ^ x = 0
    • 异或运算满足交换律和结合律:a ^ b ^ a = (a ^ a) ^ b = 0 ^ b = b
  2. 算法步骤

    • 初始化 result = 0
    • 遍历数组,对每个元素执行 result ^= num
    • 最终 result 就是唯一出现一次的数字。
代码实现
public class SingleNumber {public static int singleNumber(int[] nums) {int result = 0; // 初始时 result=0,不影响第一次运算for (int num : nums) {result ^= num;}return result;}public static void main(String[] args) {int[] nums = {4, 1, 2, 1, 2};System.out.println("唯一出现一次的数字是: " + singleNumber(nums)); // 输出: 4}
}
代码解释
  1. 方法 singleNumber

    • 初始化 result0
    • 使用增强 for 循环遍历数组 nums,对每个元素 num 执行异或操作 result ^= num
    • 最终返回 result,即唯一出现一次的数字。
  2. 主方法 main

    • 定义一个测试数组 nums,其中 4 是唯一出现一次的数字。
    • 调用 singleNumber 方法并打印结果。
复杂度分析
  • 时间复杂度O(n),只需遍历数组一次。
  • 空间复杂度O(1),仅使用常数空间存储 result
示例运行

输入:[4, 1, 2, 1, 2]
输出:唯一出现一次的数字是: 4

进阶问题

如果数组中有两个数字只出现一次,其他数字都出现两次,如何找出这两个数字?
提示

  1. 先异或所有数字得到 xorSum
  2. 找到 xorSum 的任意一个为 1 的位(如最低位的 1)。
  3. 根据该位将数组分成两组,分别异或得到两个唯一数字。

Java 实现示例

public static int[] findTwoSingleNumbers(int[] nums) {int xorSum = 0;for (int num : nums) {xorSum ^= num;}int diffBit = xorSum & -xorSum; // 找到最右边的不同位int[] result = new int[2];for (int num : nums) {if ((num & diffBit) == 0) {result[0] ^= num;} else {result[1] ^= num;}}return result;
}

二进制数1

牛客网 : 二进制数1

在这里插入图片描述

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;public class Main{public static void main(String[] args) throws IOException {BufferedReader br=new BufferedReader(new InputStreamReader(System.in));long lnum=Long.parseLong(br.readLine());br.close();System.out.println(Long.bitCount(lnum));}
}

二进制不同位数

牛客网 : 二进制不同位数

在这里插入图片描述

import java.io.*;
import java.util.*;public class Main {public static void main(String[] args) throws IOException {BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));String s = null;while ((s = reader.readLine()) != null) {String[] cs = s.split(" ");//int n = Integer.parseInt(s);//异或,相同是0,不同是1,先异或,再统计1的个数int a = Integer.parseInt(cs[0]);int b = Integer.parseInt(cs[1]);int c = a ^ b;int res=0;while (c!=0){res+=c&1;c=c>>>1;}System.out.println(res);}}}
http://www.lqws.cn/news/531919.html

相关文章:

  • 光场操控新突破!3D 光学信息处理迎来通用 PSF 工程时代--《自然》子刊:无需复杂算法,这一技术让 3D 光学成像实现 “即拍即得”念日
  • AI智能体——OpenManus 源码学习
  • [3D-portfolio] 版块包装高阶组件(封装到HOC) | Email表单逻辑 | 链式调用
  • Mac mini 跑 DeepSeek R1 及 QwQ-32B模型实测报告
  • 记dwz(JUI)前端框架使用之--服务端响应提示框
  • Jenkins与Kubernetes深度整合实践
  • 从零开始理解百度语音识别API的Python实现
  • Trae IDE 大师评测:驾驭 MCP Server - Figma AI Bridge 一键成就前端瑰宝
  • HDC 2025丨华为云AI原生中间件,构建应用运行的领先架构
  • DAY 43 复习日
  • docker 安装Elasticsearch + kibana + ik分词器
  • (七)Dockerfile文件20个命令大全详解
  • 【数据结构】--排序算法
  • Java--程序控制结构(下)
  • RK3568-休眠唤醒关机开机流程
  • 【NLP】自然语言项目设计02
  • MySQL (一):数据类型,完整性约束和表间关系
  • 12345政务热线系统:接诉即办,赋能智慧城市治理
  • 指标中台+大模型:解密衡石Agentic BI的NL2DSL架构实现
  • Prompt工程解析:从指令模型到推理模型的提示词设计
  • Linux 和 Windows 服务器:哪一个更适合您的业务需求?
  • 黑马JVM解析笔记(四):Javap图解指令流程,深入理解Java字节码执行机制
  • 创建Django项目
  • JVM调优实战 Day 7:JVM线程分析与死锁排查
  • 动态库与静态库【Linux】
  • 前端替换打包后文件中的内容方案(可用于渗透测试后将问题版本号清空临时解决方案)
  • 事务相关问题
  • 数学:逆元,同余
  • 热点代码探测确定何时JIT
  • Codeforces Educational Round 180 题解