【算法系列篇】位运算

在这里插入图片描述

文章目录

  • 前言
  • 什么是位运算算法
  • 1.判断字符是否唯一
    • 1.1 题目要求
    • 1.2 做题思路
    • 1.3 Java代码实现
  • 2. 丢失的数字
    • 2.1 题目要求
    • 2.2 做题思路
    • 2.3 Java代码实现
  • 3. 两数之和
    • 3.1 题目要求
    • 3.2 做题思路
    • 3.3 Java代码实现
  • 4. 只出现一次的数字
    • 4.1 题目要求
    • 4.2 做题思路
    • 4.3 Java代码实现
  • 5. 消失的两个数字
    • 5.1 题目要求
    • 5.2 做题思路
    • 5.3 Java代码实现
  • 总结

前言

位操作符想必大家都知道吧,&——按位与,|——按位或,^——按位异或,~——按位取法,位操作主要是用来操作二进制数的,就是因为它操作的是二进制,所以它的速度非常的快,那么既然他的速度很快,我们是否可以用位运算来解决一些实际问题呢?当然是可以的,这篇文章我将为大家分享如何使用位运算这种算法来解决一些问题。

什么是位运算算法

位运算算法是一组基于二进制位的操作符和操作方法的算法,用于在计算机中对二进制数字进行快速和高效的操作。位运算算法可以在二进制位级别上进行操作,包括位与(AND)、位或(OR)、位异或(XOR)、位取反(NOT)以及移位操作(左移和右移)等。

  • 按位与(&):只有当两个比特位都为1的时候结果才为1,否则为0
  • 按位或(|):两个比特位中有一个1,结果就为1
  • 按位异或(^):两个比特位相同为0,相异为1
  • 按位取反(~):除符号位之外,其它的比特位取反,为0结果为1,为1结果为0

位运算算法常用于以下情况:

  1. 位操作:可以通过位与、位或、位异或等运算符来对二进制数字的每一位进行操作,实现快速的位级别操作。
  2. 位掩码:可以使用位运算来创建和操作掩码,掩码经常用于标志位、权限控制和位字段的操作。
  3. 整数运算优化:位运算算法可以实现某些整数运算的高效实现,如乘以2的幂次方、除以2的幂次方、判断奇偶性等。
  4. 位图算法:位运算常用于位图算法,其中每个二进制位表示集合中的一个元素,可以进行高效的集合操作,如并集、交集、差集等。
  5. 压缩算法:位运算可以在压缩算法中起到重要的作用,用于压缩和解压缩数据,常见的例子包括哈夫曼编码和算术编码。

位运算算法通常具有高效性、简洁性和可移植性的特点,可以提供快速的底层操作,特别适合某些特定的问题和应用领域。在编写低级别的系统程序、嵌入式系统、网络协议和算法优化等方面,位运算算法发挥着重要的作用。

1.判断字符是否唯一

https://leetcode.cn/problems/is-unique-lcci/

1.1 题目要求

实现一个算法,确定一个字符串 s 的所有字符是否全都不同。

示例 1:

输入: s = "leetcode"
输出: false 

示例 2:

输入: s = "abc"
输出: true

限制:

  • 0 <= len(s) <= 100
  • s[i]仅包含小写字母
  • 如果你不使用额外的数据结构,会很加分。
class Solution {public boolean isUnique(String astr) {}
}

1.2 做题思路

通常判断唯一性的时候,我们首先想到的是哈希表,但是这里限制我们不适用额外的数据结构,我们虽然可以使用数组来模拟哈希表,但这都不是最优解,这道题最优的解法就是使用位图的思想。为什么会选择使用位图呢?因为题目中说明了:字符串中只包含小写字母,也就是无重复字符的字符串的长度最长为26,而一个整型0有4个字节,32个比特位,并且二进制的0和1则恰好可以标志某一字符有或者没有。

那么如何使用位图的思想来解决这个问题呢?我们可以将每一个字符所代表的ASCII码值来表示它在32个比特位中的位置,用循环来遍历字符串中的每一个字符,如果该字符在32个比特位中的对应位置是0的话,则用 | 运算,将该位置变为1,如果该位置为 1 的话,则说明出现了重复的字符。

1.3 Java代码实现

class Solution {public boolean isUnique(String astr) {//鸽巢原理,当字符串长度大于26的时候一定会有重复的字符if(astr.length() > 26) return fasle; int tmp = 0; //tmp 代表32位比特位的位图for(int i = 0; i < astr.length(); i++) {char ch = astr.charAt(i);if(((tmp >> (ch - 'a')) & 1) == 1) return false;else tmp = tmp | (1 << (ch - 'a'));}return true;}
}

在这里插入图片描述

2. 丢失的数字

https://leetcode.cn/problems/missing-number/

2.1 题目要求

给定一个包含 [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 <= 104
  • 0 <= nums[i] <= n
  • nums 中的所有数字都 独一无二
class Solution {public int missingNumber(int[] nums) {}
}

2.2 做题思路

这道题目的意思就是,原本数组中的元素应该是[0,数组长度],但是数组中缺少了一个数字,我们需要找到这个缺失的数字。这个题有很多种解法:

  1. 哈希表。
  2. 高斯求和。将原本数组中的元素的和减去现有数组所有元素的和就得到缺失的那个数字
  3. 排序。将数组进行排序,然后遍历数组找到缺失的那个数字
  4. 位运算

能用位运算解决就尽量用位运算来解决,因为位运算的速度非常快,那么这道题如何使用位运算来解决呢?在这之前,我们需要知道,^ 操作,当两个相同的数字进行异或操作的时候结果为0,那么我们可以将原本数组中元素和现有数组中的元素都进行异或操作,相同的两个数异或结果为0,到最后异或的结果就是我们要找的那个缺失的数字。

2.3 Java代码实现

class Solution {public int missingNumber(int[] nums) {int ret = 0;for(int n : nums) ret ^= n;for(int i = 0; i <= nums.length; i++) ret ^= i;return ret;}
}

在这里插入图片描述

3. 两数之和

https://leetcode.cn/problems/sum-of-two-integers/

3.1 题目要求

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

示例 1:

输入:a = 1, b = 2
输出:3

示例 2:

输入:a = 2, b = 3
输出:5

提示:

  • -1000 <= a, b <= 1000
class Solution {public int getSum(int a, int b) {}
}

3.2 做题思路

两数之和,大家一看到这个题目可能就会觉得很简单,直接 return a + b; 不就行了吗?但是仔细看题目,这道题不允许使用运算符 + 和 -,那么如何在不使用运算符的情况下实现两数之和呢?位运算,通过位运算就可以在不适用运算符的情况下实现两数之和的运算。

当我们进行二进制的加法的时候,当两个比特位相加的结果为2的时候,就需要向前进一位,但是我们可以先使用 ^ 操作来进行无进位的加法,当两个比特位相加的结果为2时,不进行进位而得到的结果,然后再使用 & 操作,来得到什么时候该进位,然后将 & 的结果向左移动一位,将上面的两个结果再循环进行上面的操作,直到 & 得到的结果为0的时候,就得到了两数之和的结果。

在这里插入图片描述

3.3 Java代码实现

class Solution {public int getSum(int a, int b) {while(b != 0) {int x = a ^ b;int y = a & b;a = x;b = y << 1;}return a;}
}

在这里插入图片描述

4. 只出现一次的数字

https://leetcode.cn/problems/single-number-ii/

4.1 题目要求

给你一个整数数组 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 中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次
class Solution {public int singleNumber(int[] nums) {}
}

4.2 做题思路

通过题目,我们可以知道,除了那个只出现了一次的数字之外,其他的数字都出现了一次,所以呢,我们可以将数组中的每个元素的32个比特位分别相加,将结果 % 3,就会得到那个只出现一次的数字的对应比特位。
在这里插入图片描述

4.3 Java代码实现

class Solution {public int singleNumber(int[] nums) {int ret = 0;for(int i = 0; i < 32; i++) {int tmp = 0;for(int n : nums) {tmp += (n >> i) & 1;}ret |= (tmp % 3) << i;}return ret;}
}

在这里插入图片描述

5. 消失的两个数字

https://leetcode.cn/problems/missing-two-lcci/

5.1 题目要求

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

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

示例 1:

输入: [1]
输出: [2,3]

示例 2:

输入: [2,3]
输出: [1,4]

提示:

  • nums.length <= 30000
class Solution {public int[] missingTwo(int[] nums) {}
}

5.2 做题思路

这个题目跟上面的消失的一个数字其实是类似的,只不过这里出现了两个消失的数字,我们不可能一次就找到两个消失的数字,但是我们可以分两次找。可以将这道题目转换为数组中只出现了一次的数字,这里大家可以看看我之前写过的一篇文章寻找单身狗,但是呢一个数组中只能找到一个只出现了一次的数字,如果要想找到两个只出现了一次的数字,我们可以将这两个消失的数组分别给分到两个不同的数组中,然后在每一个数组中找那个只出现了一次的数字,最终这两个消失的数字都会被找到。那么,如何将这两个消失的数字分在两个不同的数组中呢?同样是将原本的数组和现有的数组中的所有元素都进行异或操作,相同的元素异或为0,最后剩下的其实就是这两个消失的数字异或的结果,然后我们需要在这个异或的结果中找到比特位为 1 的位置,因为异或,相异为 1 ,相同为0,当找到这个为 1 的比特位之后,就可以将这些元素进行分组了,该比特位为 1 的为一组,为 0 的为另一组。

在这里插入图片描述

5.3 Java代码实现

class Solution {public int[] missingTwo(int[] nums) {int[] ret = new int[2];int tmp = 0;for(int n : nums) tmp ^= n;for(int i = 1; i <= nums.length + 2; i++) tmp ^= i;int flg = 0; //用来记录异或结果比特位为1的位置for(int i = 0; i < 32; i++) {if(((tmp >> i) & 1) == 1) {flg = i;break;}}for(int n : nums) {if(((n >> flg) & 1) == 1) ret[0] ^= n;else ret[1] ^= n;}for(int i = 1; i <= nums.length + 2; i++) {if(((i >> flg) & 1) == 1) ret[0] ^= i;else ret[1] ^= i;}return ret;}
}

在这里插入图片描述

总结

通过本篇博客,我们深入了解了位运算算法及其在计算机领域中的重要性和应用。位运算算法是一项强大的工具,它基于二进制位的操作,能够高效地处理二进制数据,提升程序的性能和效率。

在实际应用中,我们可以利用位运算算法来实现各种位级别的操作,如位掩码、位操作、整数运算优化、位图算法和压缩算法等。这些算法和技巧可以在底层系统编程、嵌入式系统、网络协议和算法优化等领域发挥重要作用。

然而,在使用位运算算法时,也需要注意一些优化技巧和注意事项。我们需要注意位运算的优先级、位移操作的性能和溢出问题,以及如何利用位运算进行快速乘法、除法和判断奇偶性等操作。深入理解这些技巧,能够更好地应用位运算算法,提高代码的效率和准确性。

位运算算法是计算机科学中一个广泛应用的领域,通过深入学习和实践,我们可以进一步探索和发现更多有趣的位运算技巧和应用。在日常编程中,合理运用位运算算法,能够帮助我们解决一些复杂的问题,实现更高效和可靠的程序。

希望本篇博客能够为读者提供一个全面而清晰的位运算算法入门指南,让大家对位运算算法有更深入的了解,并能够应用于实际开发中。通过不断学习和探索,我们可以进一步提升自己的编程能力,并在算法领域中取得更多的成就。

感谢您的阅读,希望本篇博客对您有所帮助。如果您有任何问题或反馈,欢迎留言交流。祝愿您在位运算算法的学习和应用中取得成功!

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

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

相关文章

[ 云计算 | AWS ] Java 应用中使用 Amazon S3 进行存储桶和对象操作完全指南

文章目录 一、前言二、所需 Maven 依赖三、先决必要的几个条件信息四、创建客户端连接五、Amazon S3 存储桶操作5.1. 创建桶5.2. 列出桶 六、Amazon S3 对象操作6.1. 上传对象6.2. 列出对象6.3. 下载对象6.4. 复制、重命名和移动对象6.5. 删除对象6.6. 删除多个对象 七、文末总…

学习pytorch6 torchvision中的数据集使用

torchvision中的数据集使用 1. torchvision中的数据集使用官网文档注意点1 totensor实例化不要忘记加括号注意点2 download可以一直保持为True代码执行结果 2. DataLoader的使用 1. torchvision中的数据集使用 官网文档 注意左上角的版本 https://pytorch.org/vision/0.9/ 注…

深度学习10:Attention 机制

目录 Attention 的本质是什么 Attention 的3大优点 Attention 的原理 Attention 的 N 种类型 Attention 的本质是什么 Attention&#xff08;注意力&#xff09;机制如果浅层的理解&#xff0c;跟他的名字非常匹配。他的核心逻辑就是「从关注全部到关注重点」。 Attention…

冠达管理:火爆!拼多多飙涨15%,中概股沸腾!这些外资巨头唱多中国资产

当地时间8月29日&#xff0c;美国三大股指团体收涨&#xff0c;道指涨0.85%&#xff0c;标普500指数涨1.45%&#xff0c;纳指涨1.74%。科技股大涨&#xff0c;特斯拉涨7.69%&#xff0c;英伟达涨4.16%。纳斯达克我国金龙指数收涨3.7%&#xff0c;拼多多涨超15%。 广东研山私募…

解析经典面试题:for 循环中的 let var

更多文章可以看看我的博客&#xff1a;https://icheng.github.io/ 题目 for循环中&#xff0c;使用 var 或 let 声明 i 变量&#xff0c;会得到不同的结果 var arr []; for (var i 0; i < 2; i) {arr[i] function () {console.log(i);} } arr[0](); arr[1]();输出&…

6.Redis-hash

hash 哈希类型中的映射关系通常称为field-value&#xff0c;⽤于区分 Redis 整体的键值对&#xff08;key-value&#xff09;&#xff0c;注意这⾥的value是指field对应的值&#xff0c;不是键&#xff08;key&#xff09;对应的值&#xff0c;请注意 value 在不同上下⽂的作⽤…

Codeforces Round 888 (Div. 3)

Codeforces Round 888 (Div. 3) A. Escalator Conversations 思路&#xff1a;暴力枚举 我们可以发现要让他们能相同高度首先你们之间的差值必须是k的倍数并且这个倍数必须小于m并且不能存在相同高度 #include<bits/stdc.h> using namespace std; #define int long lo…

重磅!OpenAI突然发布企业版ChatGPT:没有限制、更快、更强、更安全的GPT-4

这是由【小瑶智能体】 AI创作的第 4 篇科技文章 大模型研究测试传送门 GPT-4传送门&#xff08;免墙&#xff0c;可直接测试&#xff0c;遇浏览器警告点高级/继续访问即可&#xff09;&#xff1a;Hello, GPT4! 大家好&#xff0c;我是小瑶智能体&#xff0c;一个喜欢分享人…

二叉搜索树(C++)

二叉搜索树 概念二叉搜索树的应用二叉搜索树的实现K模型基本结构和函数声明接口实现①find——查找关键码②Insert——插入关键码③Erase——删除关键码&#xff08;重点&#xff09;时间复杂度 源码&#xff08;整体&#xff09;非递归递归 KV模型 在使用C语言写数据结构阶段时…

安防监控/视频汇聚平台EasyCVR调用rtsp地址返回的IP不正确是什么原因?

安防监控/云存储/磁盘阵列存储/视频汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等&#xff0c;以及厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等&#xff0c;能对外分发RTSP、RT…

Linux系统下vim常用命令

一、基础命令&#xff1a; v:可视模式 i:插入模式 esc:命令模式下 :q &#xff1a;退出 :wq &#xff1a;保存并退出 ZZ&#xff1a;保存并退出 :q! &#xff1a;不保存并强制退出二、在Esc下&#xff1a; dd : 删除当前行 yy:复制当前行 p:复制已粘贴的文本 u:撤销上一步 U:…

【【萌新的STM32-22中断概念的简单补充】】

萌新的STM32学习22-中断概念的简单补充 我们需要注意的是这句话 从上面可以看出&#xff0c;STM32F1 供给 IO 口使用的中断线只有 16 个&#xff0c;但是 STM32F1 的 IO 口却远远不止 16 个&#xff0c;所以 STM32 把 GPIO 管脚 GPIOx.0~GPIOx.15(xA,B,C,D,E,F,G)分别对应中断…

Pillow:Python的图像处理库(安装与使用教程)

在Python中&#xff0c;Pillow库是一个非常强大的图像处理库。它提供了广泛的图像处理功能&#xff0c;让我们可以轻松地操作图像&#xff0c;实现图像的转换、裁剪、缩放、旋转等操作。此外&#xff0c;Pillow还支持多种图像格式的读取和保存&#xff0c;包括JPEG、PNG、BMP、…

【已解决】ZooKeeper配置中出现Error contacting service. It is probably not running

ZooKeeper配置中出现Error contacting service. It is probably not running 问题 安装zookeeper&#xff0c;启动报错了 Error contacting service. It is probably not running 思路 tail -100f logs/zookeeper-root-server-node1.itcast.cn.out 查看日志报错 zoo.cfg没…

FPGA VR摄像机-拍摄和拼接立体 360 度视频

本文介绍的是 FPGA VR 相机的第二个版本&#xff0c;第一个版本是下面这样&#xff1a; 第一版地址&#xff1a; ❝ https://hackaday.io/project/26974-vr-camera-fpga-stereoscopic-3d-360-camera ❞ 本文主要介绍第二版本&#xff0c;第二版本的 VR 摄像机&#xff0c;能够以…

使用 Privoxy 在 Linux 上配置本地代理服务器详细教程

Privoxy 是一个功能强大的开源网络代理软件&#xff0c;它可以帮助我们在 Linux 系统上搭建本地代理服务器。通过配置和使用 Privoxy&#xff0c;您可以实现更安全、匿名以及自定义过滤规则等高级特性。本文将详细介绍如何在 Linux 环境下利用 Privoxy 配置并运行本地代理服务器…

递归算法学习——子集

目录 一&#xff0c;题目解析 二&#xff0c;例子 三&#xff0c;题目接口 四&#xff0c;解题思路以及代码 1.完全深度搜索 2.广度搜索加上深度优先搜索 五&#xff0c;相似题 1.题目 2.题目接口 3.解题代码 一&#xff0c;题目解析 给你一个整数数组 nums &#xff0c…

拼多多anti-token分析

前言&#xff1a;拼多多charles抓包分析发现跟商品相关的请求头里都带了一个anti-token的字段且每次都不一样,那么下面的操作就从分析anti-token开始了 1.jadx反编译直接搜索 选中跟http相关的类对这个方法进行打印堆栈 结合堆栈方法调用的情况找到具体anti-token是由拦截器类f…

C语言每日一练------Day(5)

本专栏为c语言练习专栏&#xff0c;适合刚刚学完c语言的初学者。本专栏每天会不定时更新&#xff0c;通过每天练习&#xff0c;进一步对c语言的重难点知识进行更深入的学习。 今日练习题关键字&#xff1a;错误的集合 密码检查 &#x1f493;博主csdn个人主页&#xff1a;小小u…

系统架构:软件工程

文章目录 资源知识点自顶向下与自底向上形式化方法结构化方法敏捷方法净室软件工程面向服务的方法面向对象的方法快速应用开发螺旋模型软件过程和活动开放式源码开发方法功用驱动开发方法统一过程模型RUP基于构件的软件开发UML 资源 信息系统开发方法 知识点 自顶向下与自底…