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

算法基础: 位运算

位运算

目录

位运算

概念

常用操作

算法考题


概念

就是直接对存储在内存中的数据的二进制位进行操作。在计算机中,每一个二进制位称为1个bit,单位简写做 b。通常8个bit为一个单位,称为字节(byte),单位简写作 B

在C/C++中表示二进制数一般使用用0x前缀表示的十六进制形式,和二进制数有一一对应的关系,如0x5A,表示二进制数 01011010 0101 101001011010。

C++中二进制字面量直到C++14标准才补上,以0b0B表示,如 0b01011010,但C语言标准一直没有,只在GNU C编译器上有相应的扩展语法,所以在代码中以0b为前缀的数有可能编译不过。

  • 按位与运算(&), 同为1,则为1
  • 按位或运算(|),有1,则为1.
  • 按位异或运算(^),不同,则为1.
  • 求反运算(~),1则为0,0则为1.
  • <<n左移n位,右补0。实际含义相当于*2^n
  • >>n右移n位,左补0.实际含义相当于/2^n

常用操作

交换swap

异或操作

注意:必须是两块内存,不然会把自己洗成0!

int a = 10;
int b = 11;
a = a^b;
b = a^b;
b = a^b;

平均值

(x+y)>>1

取mid

L+((R-L)>>1)

2的n次方

1 << n

判断符号是否相同

(x^y)>=0


判断奇偶性

(n &1) ==1

32位int取绝对值

(n ^ (n >> 31)) - (n >> 31)

判断n是否是2的整数次幂

n&(n-1) == 0

获取一个数二进制最右面的一个1

x&((~x)+1)

算法考题

一个数组中只有一个数出现了奇数次,其他数都出现了偶数次,怎么找到这个数,

思路:相同的数被异或变为0,只有那个奇数的会留下来。

int arr[9] = {1,2,3,4,5,1,2,3,4};
int val = 0;
for(int i =0;i<9;i++) {
    val  = val^arr[i];
}

一个数组中只有两个数出现了奇数次,其他数都出现了偶数次,怎么找到这个数

思路: 如果只有两个数是奇数,那么所有值的异或结果一定包含了这两个值的异或结果,这个值的二进制就代表了剩余的两个奇数项的值的二进制不同,我们从中找到一个1的位数N。

然后就可以再使用一个数去异或N位上为1的数,这个时候就可以找到一个数,再用这个数去异或最开始全量异或算出的value,就可以得到另外一个数。

int arr[9] = {1,2,3,4,5,1,2,3,4,6};
int val1 = 0;
for(int i =0;i<9;i++) {
    val1  = val^arr[i];
}
int right_one = val1 & (~val1 +1);
int val2 =0;
for(int i =0;i<9;i++) {
    if(arr[i]&right_one == 0) {
        val2^=arr[i];
    }
}
cout <<val2 <<val2^val1<<endl;

一个数组中只有一个数出现了N数次,其他数都出现了M数次,怎么找到这个数

思路:借助一个32个元素的数组,将所有的数据的二进制(32位数)如果为1.就将数组下标对应位加1,之后判断哪些可以不可以被M整除,且余数为N

int function(vector<int32_t> arr,int k,int m)
{
    array<int,32> bit_arr{0};
    for(int index =0 ;index <arr.size();index ++) {
        for(int i =0;i<32;i++) {
            if((arr[index] & (1<<i)) != 0)
            {

                bit_arr[i] ++;
            }
            
        }
    }

    int32_t num = 0;
    int i =0;
    for(auto &a : bit_arr) {
        if(a%m == 0) {
            i++;
            continue;
        }
        if(a%m == k) {
             num |= (0x01<<i);
             i++;
        }
        
    }
    return num;
}
int main()
{
    cout<<function({1,1,1,2,2,2,3,3},2,3)<<endl;
}

 

相关文章:

  • 记录一次坑 | 包版本不一致产生的问题的排查过程
  • SmartX Everoute 如何通过微分段技术实现 “零信任” | 社区成长营分享回顾
  • “相信美好,即将发生”——天泽智云
  • 面试阿里技术专家岗,对答如流,这些面试题你能答出多少
  • Spring AOP与事务
  • 时序与空间结构
  • 一幅长文细学TypeScript(一)——上手
  • DM JDBC
  • hadoop2.2.0开机启动的后台服务脚本(请结合上一篇学习)
  • java基于springboot+vue的学生成绩管理系统 elementui
  • 测试与开发环境网址hosts配置
  • MogDB企业应用 之 Rust驱动
  • html css面试题
  • 密码学 | RC4算法Native层分析
  • 融合与创新:数据堂骨龄标注工具为医生赋能
  • 【知识碎片】第三方登录弹窗效果
  • Apache Zeppelin在Apache Trafodion上的可视化
  • CSS 专业技巧
  • css系列之关于字体的事
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • Lucene解析 - 基本概念
  • Markdown 语法简单说明
  • python学习笔记 - ThreadLocal
  • Travix是如何部署应用程序到Kubernetes上的
  • 基于HAProxy的高性能缓存服务器nuster
  • 前端路由实现-history
  • 前端自动化解决方案
  • 入手阿里云新服务器的部署NODE
  • 使用 @font-face
  • 使用Maven插件构建SpringBoot项目,生成Docker镜像push到DockerHub上
  • 《码出高效》学习笔记与书中错误记录
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • ​iOS安全加固方法及实现
  • ​iOS实时查看App运行日志
  • ​queue --- 一个同步的队列类​
  • #etcd#安装时出错
  • (4)事件处理——(7)简单事件(Simple events)
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (第一天)包装对象、作用域、创建对象
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • (三)c52学习之旅-点亮LED灯
  • (三)模仿学习-Action数据的模仿
  • (一)插入排序
  • ./configure,make,make install的作用(转)
  • .【机器学习】隐马尔可夫模型(Hidden Markov Model,HMM)
  • .NET Core IdentityServer4实战-开篇介绍与规划
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .NET 同步与异步 之 原子操作和自旋锁(Interlocked、SpinLock)(九)
  • .net 怎么循环得到数组里的值_关于js数组
  • .NET轻量级ORM组件Dapper葵花宝典
  • .NET学习教程二——.net基础定义+VS常用设置
  • .NET中winform传递参数至Url并获得返回值或文件