位运算的奇技淫巧

常见位运算总结:

1、基础位运算

左移<<运算

将二进制数向左移位操作,高位溢出则丢弃,低位补0。

右移>>运算

右移位运算中,无符号数和有符号数的运算并不相同。对于无符号数,右移之后高位补0;对于有符号数,符号位一起移动,正数高位补0,负数高位补1

按位与&运算

有0就是0,巧计:&这个符号像是有两个0组合而成。

按位或 | 运算

有1就是1,巧计:|本身就像一个1

按位异或^运算(两种解释方法)

相同为0,相异为1,或者解释成无进位相加

2、给一个数n,确定它的二进制表示中的第x位是0还是1

(n >> x) & 1

&1后的结果就是0/1,因为1的二进制位除了最后一位,其他都是0,&0就是0

3、将一个数n的二进制位的第x位改成1

n =(1 << x)|  n

4、将一个数n的二进制位的第x位改成0

n = n & (~(1 << x))

5、位图的思想

本质上就是一个哈希表

6、提取一个数(n)二进制表示中最右侧的1(lowbit

n & -n

解释:-n的操作就是先取反,然后再+1,这样造成的影响是最右边的1前面都是n的相反数,这样再跟原先的n&,因为是相反数,所以有一方肯定是0,这样最右边的1前面的数字都变成了0,最右边1右边本身就是0。

7、干掉一个数(n)最右边的1

n &(n - 1)

8、位运算的优先级

为了避免记住闲杂的公式,我们只需要记住能加括号就加括号。

9、异或运算的运算规律

  • a ^ 0 = a
  • a ^ a = 0(消消乐)
  • a ^ b ^ c = a ^ (b ^ c)

上面的指示是位运算的基础知识,下面就带着上面的指示开始实操啦

第一题:
191. 位1的个数

编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为汉明重量)。

解析:

只需要每次右移&1判断是否为1。

原码:

class Solution {
public:int hammingWeight(uint32_t n) {int sum = 0;int ret = n;for(int i = 0;i<32;i++){if(ret & 1 == 1) sum++;ret = ret >> 1;}return sum;}
};

第二题、461. 汉明距离

两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。

给你两个整数 x 和 y,计算并返回它们之间的汉明距离。

解析:

根据题目来看,可能最先想到的就是异或操作,相同为 0,不同为 1。异或操作后结果为 0101,然后我们只需要统计出来二进制结果中 1 的个数就可以计算出来汉明距离啦。

原码:

class Solution {
public:int hammingDistance(int x, int y) {int ret = x ^ y;int sum = 0;//计算1的个数for(int i = 0;i<32;i++){if(ret & 1 == 1) sum++;ret = ret >> 1;} return sum;}
};

第三题、136. 只出现一次的数字

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

解析:

这是一道很典型的运用^的题目,我们只需要理解异或运算符,这题就迎刃而解啦。

原码:

class Solution {
public:int singleNumber(vector<int>& nums) {int ret = 0;for(int i = 0;i<nums.size();i++){ret = ret ^ nums[i];}return ret;}
};

第四题、260. 只出现一次的数字 III

给你一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。

你必须设计并实现线性时间复杂度的算法且仅使用常量额外空间来解决此问题。

解析:

本题是上一题的升级版,

把nums中的元素全部异或起来的结果eor就是那两个只出现一次的数字的异或结果。而这两个数不相同,意味着eor至少有一位是1,我们可以用lowbit运算拿到最低位的1,然后遍历nums数组,将所有数nums[i]按照这一位是不是1分成两类,初始化num1=num2=0

  1. 如果当前位是1,就将nums[i]异或到num1​上。

  2. 如果当前位是0,就将nums[i]异或到num2​上。

这样一来,两个只出现一次的数就会被分别异或到num1​和num2​上,而其他数也会被分别异或到这两个数上。而由于其他数都出现了两次,所以最终它们就会被异或成0,num1​和num2​就是那两个只出现一次的数。

注意进行位运算的优先级,直接加上括号就好!!!

原码:

class Solution {
public:vector<int> singleNumber(vector<int>& nums) {int a = 0, b = 0;//记录两个不同的数int ret = 0;for(int i = 0;i<nums.size();i++)ret ^= nums[i];//进行lowbit运算,两者不同,二进制肯定有1int tmp = ret & (-(long long)ret);//防止数据溢出for(int i = 0;i<nums.size();i++){if((tmp & nums[i]) == 0)//注意优先级! a ^= nums[i];else b ^= nums[i];}return {a,b};}
};

第五题、面试题 01.01. 判定字符是否唯一

解析:

本题第一思想直接用哈希表解决,但题目中用说尽量不用数据结构,我们可以尝试用位图解决!

用位图解决,需要熟练掌握位运算技巧,对巩固位运算有很大帮助!

原码:

class Solution {
public:bool isUnique(string astr) {int bitmap = 0;//用位图思想解决int tmp = 0;int n = astr.size();//利用鸽巢原理优化if(n > 26) return false;for(int i = 0;i<astr.size();i++){tmp = astr[i] - 'a';//判断字符是否已经出现过if(((bitmap >> tmp) & 1) == 1) return false;//把当前字符加入位图中bitmap = bitmap | (1 << tmp);}return true;}
};

第六题、371. 两整数之和

给你两个整数 a 和 b ,不使用 运算符 + 和 - ,计算并返回两整数之和。

思路:

我们前面介绍了^运算的另一个功能是不进位相加,因此我们可以利用这个特性去解决这道题。

因为是不进位,所以我们要想办法去解决进位的问题,^运算是相同为0,相异为1,相异不可能进位,只有相同并且都是1的情况下,才会进位,因此我们直接&,查找出都是1,因为是进位,所以还要左移一位,(a & b)<< 1,然后分别重制a,b的值。

原码:

class Solution {
public:int getSum(int a, int b) {while(b){int tmp = a;a = a ^ b;b = ((tmp&b) << 1);}return a;}
};

第七题、137. 只出现一次的数字 II

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。

解析:

本题有点难度,两层嵌套循环,根据32位int,把每个数位相加再对3取的余数即可,将每个数想象成32位的二进制,对于每一位的二进制的1和0累加起来必然是3N或者3N+1, 为3N代表目标值在这一位没贡献,3N+1代表目标值在这一位有贡献(=1),然后将所有有贡献的位|起来就是结果。这样做的好处是如果题目改成K个一样,只需要把代码改成cnt%k,很通用~

原码:

class Solution {
public:int singleNumber(vector<int>& nums) {int ans = 0;int n = nums.size();for(int i = 0;i<32;i++)//依次去修改ans的每一位{int sum = 0;for(int j = 0;j<n;j++){//计算nums中所有数的第i位的和sum += (nums[j] >> i) & 1;}//把第i位修改if(sum % 3)   ans ^= (1 << i); }return ans;}
};

第八题、面试题 17.19. 消失的两个数字

给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗?

以任意顺序返回这两个数字均可。

解析:

本题是两道题的融合版。

  • 将所有的数异或在一起,记为tmp
  • 找到tmp中,比特位上为1的那一位
  • 根据不同的那一位,划分为两类异或

原码

class Solution {
public:vector<int> missingTwo(vector<int>& nums) {int a = 0,b = 0;int n = nums.size();int ret = 0;//先将所有数异或for(int i = 1;i<=n+2;i++)ret ^= i;for(int i = 0;i<n;i++)ret ^= nums[i];//lowbit运算找到最右边的1int tmp = ret & (-(long long)ret);//防止溢出for(int i = 0;i<n;i++){if((nums[i] & tmp) == 0) a ^= nums[i];else b ^= nums[i];}for(int i = 1;i<=n+2;i++){if((i & tmp) == 0) a ^= i;else b ^= i; }return {a,b};}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/635941.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【正点原子STM32连载】 第四十三章 FLASH模拟EEPROM实验 摘自【正点原子】APM32E103最小系统板使用指南

1&#xff09;实验平台&#xff1a;正点原子APM32E103最小系统板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/docs/boards/xiaoxitongban 第四…

自定义shell工具函数之pull_image()

这是一个名为pull_image的Shell脚本函数。让我来解释一下这个函数的功能&#xff1a; function pull_image() {image$1DOCKER_IMAGE_MIRROR$(get_config_or_env DOCKER_IMAGE_MIRROR)if [[ "${DOCKER_IMAGE_MIRROR}" "1" ]]; thenif [[ "$(uname -m…

深入解析ESP32C3(1) - 使用ESP-IDF

乐鑫ESP32系列芯片是性价比非常高的嵌入式平台&#xff0c;不仅外设接口丰富&#xff0c;有较多的存储空间&#xff0c;还支持WIFI/BT等无线连接&#xff0c;同时也支持加密和权限管理等安全功能&#xff0c;这大大拓展了芯片的应用领域&#xff1b;当然&#xff0c;最重要的是…

Python使用pyechart分析疫情确诊人数图(2024)

import json from pyecharts.charts import Map from pyecharts import options as opts# 首先打开文件获取数据 f open("/Desktop/python/Project/数据可视化/疫情.txt", "r", encoding"UTF-8") data f.read()# 字符串转化成json数据 data_js…

Java多线程--创建多线程的基本方式一:继承Thread类

文章目录 一、创建和启动线程&#xff08;1&#xff09;概述&#xff08;2&#xff09;方式1&#xff1a;继承Thread类1、使用步骤2、举例2.1 案例12.2 案例22.3 案例3 3、两个问题3.1 问题13.2 问题2 4、代码及总结 二、练习&#xff08;1&#xff09;方式一&#xff08;2&…

索引的概述和性能分析

索引index&#xff0c;是一种有序的数据结构&#xff0c;可以高效的获取数据&#xff0c;在数据库中维护着满足查找特定算法的数据结构&#xff0c;就是索引 无索引的情况&#xff0c;查询数据时会全表扫描&#xff0c;效率极低 索引结构 &#xff08;1&#xff09;二叉树&…

python解决求二叉树的最长同值路径问题

对于给定的一颗二叉树&#xff0c;需要找到最长的路径&#xff0c;并且该路径上的每个节点具有相同的值的问题&#xff0c;对于寻找到的这条路径可以经过根节点也可以不经过根节点&#xff0c;两个节点之间的路径长度是由他们的变数来表示的&#xff0c;给定如下图的二叉树 添加…

【 Qt 快速上手】-②- Qt 环境搭建

文章目录 1. Qt 开发工具概述1.1 Qt Creator 介绍1.2 Visual Studio 介绍1.3 Eclipse 介绍 2. Qt SDK 的下载与安装2.1 Qt SDK 的下载2.2 Qt SDK 的安装2.3 验证 Qt SDK 安装是否成功2.4 Qt 环境变量配置 1. Qt 开发工具概述 Qt 开发环境需要安装三个部分&#xff1a; C编译器…

小伙频繁发朋友圈引发分手,拼命“晒“生活是否成为一种病态行为?

根据《西湖之声》1月19日的报道&#xff0c;一个小伙子因为一天发十几条朋友圈而引起了他女友的不满&#xff0c;女友甚至提出了分手。现如今&#xff0c;朋友圈已经成为每个人自我形象展示的平台&#xff0c;认真发朋友圈不仅是表达自己的一种方式&#xff0c;也是一种自我释放…

redis缓存和本地缓存的应用设计

数据查询顺序 一级缓存&#xff1a;本地缓存 -》二级缓存&#xff1a;redis缓存 -》数据库 本地缓存和分布式缓存 本地缓存&#xff1a;基于jvm, 意思是程序放在哪&#xff0c;数据就存储在哪&#xff0c;不需要网络请求&#xff0c;特别快&#xff0c;但是需要占用jvm的内存…

Python利用Excel读取和存储测试数据完成接口自动化教程

http_request2.py用于发起http请求 #读取多条测试用例#1、导入requests模块import requests#从 class_12_19.do_excel1导入read_data函数from do_excel2 import read_datafrom do_excel2 import write_datafrom do_excel2 import count_case#定义http请求函数COOKIENonedef ht…

Unity之四元数计算

四元数相乘 #region 四元数相乘 Quaternion q Quaternion.AngleAxis(20, Vector3.up); this.transform.rotation * q; #endregion 四元数乘向量 Vector3 v Vector3.forward; print(v); //四元数乘向量的顺序不能改变&#xff0c;也就是说不能用向量去乘四元数&#xff0c;…

Spring Boot Aop 执行顺序

Spring Boot Aop 执行顺序 1. 概述 在 spring boot 项目中&#xff0c;使用 aop 增强&#xff0c;不仅可以很优雅地扩展功能&#xff0c;还可以让一写多用&#xff0c;避免写重复代码&#xff0c;例如&#xff1a;记录接口耗时&#xff0c;记录接口日志&#xff0c;接口权限&…

C# byte转int:大小端读取

参考&#xff1a;byte[]数组和int之间的转换 文章目录 Byte转为INT小端存储方式转int大端存储方式转int 大端模式和小端模式是计算机存储多字节数据时的两种方式。内存地址从小往大增长。 大端模式&#xff1a;最高有效&#xff08;最高位&#xff09;的字节存放在最小地址上&…

python 自动化模块 - pyautogui初探

python 自动化模块 - pyautogui 引言一、安装测试二、简单使用三、常用函数总结 引言 在画图软件中使用pyautogui拖动鼠标&#xff0c;画一个螺旋式的正方形 - (源码在下面) PyAutoGUI允许Python脚本控制鼠标和键盘&#xff0c;以自动化与其他应用程序的交互。API的设计非常简…

限流算法之流量控制的平滑之道:滑动时间窗算法

文章目录 引言简介优点缺点样例样例图样例代码 应用场景结论 引言 在互联网应用中&#xff0c;流量控制是一个重要的组件&#xff0c;用于防止系统过载和保护核心资源。常见的限流算法包括固定窗口算法和滑动时间窗算法。本文将重点介绍滑动时间窗算法&#xff0c;并分析其优缺…

【设计模式 行为型】策略模式

它允许在运行时根据需要选择算法的行为。该模式通过将算法封装成独立的类&#xff0c;使得它们可以相互替换&#xff0c;而不影响使用算法的客户端代码。 策略模式主要包含以下角色&#xff1a; 环境&#xff08;Context&#xff09;&#xff1a;环境对象持有一个策略对象的引…

基于Abaqus的三种钢筋混凝土梁数值模拟对比研究

混凝土结构抗压强度高&#xff0c;而抗拉强度大约只有其十分之一&#xff0c;在受到竖向荷载&#xff08;包括自重&#xff09;作用下&#xff0c;梁下部会产生拉应力&#xff0c;上部产生压应力&#xff0c;而由于其抗拉强度低&#xff0c;因此很小的荷载即可导致梁下部开裂&a…

pytorch学习(二)、网络的构建和卷积层

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、nn.Module&#xff08;网络的构建&#xff09;二、torch.nn.functional.conv2d&#xff08;卷积运算&#xff09;三、神经网络--卷积层&#xff08;一层卷积…

Mysql中的日志系统

文章目录 1. 慢查询日志&#xff08;Slow Query Log&#xff09;1.1 是否开启慢查询日志1.2 开启慢查询日志&#xff0c;设置时间阈值1.2.1 修改文件my.ini1.2.2 重启mysql后配置生效 1.3 查看慢查询日志1.3.1 直接用文本编辑器打开1.3.2 使用mysqldumpslow进行分析 2. InnoDB …