数据结构与算法:位运算专题

本文深入探讨了位运算在数据结构与算法中的应用,包括按位与、按位或、按位异或和移位运算。通过实例解析了如何利用位运算优化算法,如PIPI的位运算问题,强调了按位考虑的思想在解题中的关键作用,提供了相应的解题思路和代码实现。文章还讨论了如何利用位运算快速判断数字奇偶性、进行状态压缩等技巧,展示了位运算在提高算法效率方面的潜力。
摘要由CSDN通过智能技术生成

数据结构与算法:位运算专题

位运算基础

  位运算指的是直接对二进制位进行的一系列操作。常用的位运算有以下几种:

  • AND(按位与):运算符为&,作用是把两个数字对应的二进制位相与,只有对应的两个位为1,结果位才为1,否则结果位为0。比如:13&12=1101&1100=1100=12。
  • OR(按位或):运算符为|,作用是把两个数字对应的二进制位相或,只有对应的两个位为0,结果位才为0,否则结果位为1。比如:9|10=1001|1010=1011=11。
  • XOR(按位异或):运算符为 ^ ,作用是把两个数字对应的二进制位相异或,如果对应的两个位不同,结果位为1;如果对应的两个位相同,结果位为0。比如:13 ^ 12=1101 ^ 1100=0001=1。
  • 移位运算:
      a. 左移运算:运算符为<<,作用是在二进制表示下把数字同时向左移, 低位以0填充, 高位越界后舍弃。比如2<<1=…00010<<1=…00100=4。
      b. 右移运算:运算符为>>,作用是在二进制表示下把数字同时向右移,高位以0填充,低位越界后舍弃。比如2>>1=…00010>>1=…00001=1。

  利用以上几种位运算操作,可以实现这些常用功能:

  • if((1<<i)&x),判断x二进制上的第i位是否为1。
  • x^(1<<i),将x二进制上的第i位取反。
  • x|(1<<i) ,将x二进制上的第i位赋值为1。
  • x>>1,等价于x/2,效率上比使用除法运算符更快。
  • if(x&1),判断奇偶,当x为奇数,其二进制上的最低位为1;当x为偶数,其二进制上的最低位为0。
  • 状态压缩,以一个二进制数表示一个状态集合。比如我们进行二进制枚举:for(i=0;i<(1<<4);i++),就是从0000~枚举到1111,那么i的第j位为0表示不取这个数字,i的第j位为1表示取这个数字。状态压缩常用于搜索/动态规划等题目。

位运算例题

例题1:PIPI的位运算问题Ⅳ
问题

在这里插入图片描述
在这里插入图片描述

解题思路

  对于大部分位运算的问题,我们需要掌握按位考虑的思想什么是按位考虑呢?也就是不对数字整体考虑,而是把数字转换成二进制形式,从它的每一位来思考解题的方法
  例如对于此题,题目是要计算第i个数与前i - 1个数的异或之和,那么我们就需要把这些数字都看成二进制形式,第i个数与其前某个数相异或,当第i个数的第j位与另一个数的第j位不同时,ans就需要加上2 ^ (j - 1)。对于前i - 1个数,计算方式都一样,于是我们就要按位考虑,计算每一位对答案ans的贡献:如果第i个数字的第j位为1,那么它对最终答案的贡献就是前i-1个数第j位为0的个数 * 2 ^ (j - 1);如果第i个数字的第j位为0,那么它对最终答案的贡献就是前i-1个数第j位为1的个数 * 2 ^ (j - 1)
  因此我们用i遍历的时候使用一个JthBitHasOne数组,JthBitHasOne[j]表示前i-1个数第j位为1的有JthBitHasOne[j]个,那么前i-1个数第j位为0的就有i-1-JthBitHasOne[j]个。一个不超过1e9的数字最多只要遍历到第29位,根据上面提到的按位考虑算贡献的方法,我们就可以把题面上O(n^2)的时间复杂度优化成O(n*log(max(ai)))。

  接下来通过样例(1,2,3)来理解这个按位考虑计算贡献的方法:
  当i=1,前面没有数能与它异或,此时ans=0。
  当i=2,a2的二进制形式为10。a2的第0位为0,根据异或的特性,相同为0,不相同为1,那么前i-1个数第0位为1的,都能对最终答案产生2 ^ 0的贡献。前i-1个数只有a1一个数第0位为1,因此对答案的贡献是1 x 2 ^ 0=1。则ans+=1,此时ans=1。
  a2的第1位为1,根据异或的特性,相同为0,不相同为1,那么前i-1个数第1位为0的,都能对最终答案产生2 ^ 1的贡献。前i-1个数只有a1一个数第1位为0,因此对答案的贡献是1 x 2 ^ 1=2。则ans+=2,此时ans=3。
  当i=3,a3的二进制形式为11。a3的第0位为1,根据异或的特性,相同为0,不相同为1,那么前i-1个数第0位为0的,都能对最终答案产生2 ^ 0的贡献。前i-1个数只有a2一个数第0位为0,因此对答案的贡献是1 x 2 ^ 0=1。则ans+=1,此时ans=4。
  a3的第1位为1,根据异或的特性,相同为0,不相同为1,那么前i-1个数第1位为0的,都能对最终答案产生2 ^ 1的贡献。前i-1个数只有a1一个数第1位为0,因此对答案的贡献是1x2^1=2。则ans+=2,此时ans=6。因此最终答案就是6。
在这里插入图片描述

代码
import java.util.*;

public class Main {
   
    static int[] JthBitHasOne = new int[32];
    static long[] twoPower = new long[
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

happy19991001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值