位运算总结(Java)

目录

位运算概述

位运算符

位运算的优先级

位运算常见应用

1. 给定一个数n,判断其二进制表示中的第x位是0还是1

 2. 将数n的二进制表示中的第x位修改为1

3. 将数n的二进制表示中的第x位修改为0

4. 位图

例题:判断字符是否唯一

5. 提取数n的二进制表示中的最右侧的1(lowbit)

6. 去掉数n的二进制表示中的最右侧的1

例题:位1的个数

7. 异或(^)运算的运算律

例题:只出现一次的数字

位运算练习

练习1:两整数之和

练习2:只出现一次的数字II

练习3:只出现一次的数字III

练习4:消失的两个数字


位运算概述

位运算:计算机中的数据在内存中是以二进制形式进行存储的,而位运算是对二进制数进行操作的运算,能够按位对数字进行操作

位运算符

(1)与运算符(&):如果两个二进制数的同一位都为1,则结果为1,否则为0。(有0为0)

(2)或运算符(|):如果两个二进制数的同一位至少有一个为1,则结果为1,否则为0。(有1为1)

(3)异或运算符(^):如果两个二进制数的同一位不相同,则结果为1,否则为0。也可以理解为 无进位相加(即0 + 0 = 0;0 + 1 = 1;而当1+1时,结果为0,但不进位)

(4)取反运算符(~):将二进制数的每一位取反,即0变为1,1变为0。

(5)左移运算符(<<):将二进制数向左移动指定的位数,右边补0。

(6)右移运算符(>>):将二进制数向右移动指定的位数,左边补0或者补1(取决于原数字的符号位)。

(7)复合赋值运算符:

&=        a&=b   同      a=a&b

|=         a|=b     同     a=a|b

>>=      a>>=b  同     a=a>>b

<<=      a<<=b  同      a=a<<b

注:对于负数的位操作,一般会使用补码表示法。在补码表示法中,最高位为符号位,0表示正数,1表示负数。位操作对于负数的结果仍然是以补码形式表示的。

位运算的优先级

常见位运算的优先级顺序:

(1)括号(()):括号可以用来改变运算符的结合性和优先级。

(2)取反运算符(~):取反运算符的优先级较高。

(3)左移运算符(<<)、右移运算符(>>)、无符号右移运算符(>>>):左移和右移运算符的优先级相同,且比与、或、异或运算符低。

(4)与运算符(&):与运算符的优先级较低。

(5)异或运算符(^):异或运算符的优先级较低于与运算符。

(6)或运算符(|):或运算符的优先级最低。

注:位运算符的优先级较低,因此在进行位运算操作时,可以使用括号来明确运算符的优先级和结合性

位运算常见应用

1. 给定一个数n,判断其二进制表示中的第x位是0还是1

例如:

在这里,我们从右侧第零位开始计数 

要判断一个数的第x位是0还是1,只需要将x向右移动x位(>> x),再与(&) 上1,即可判断,

(n >> x) & 1 

 2. 将数n的二进制表示中的第x位修改为1

例如:

要将第x位上的0修改为1,我们可以想到或(|)运算符,当两个二进制数的同一位至少有一个为1,则该位结果为1

因此,我们可以将1左移x位再让n与其进行或运算,即n |= (1 << x)

3. 将数n的二进制表示中的第x位修改为0

与将第x位修改为1类似,我们可以想到与(&)运算符,当两个二进制数的同一位至少有一个为0,则该位结果为0

因此,我们将1左移x位,再对其按位取反,这样就使得第x位为0,其他位都为1,然后再进行与运算,即 n &= (~ (1 << x))

4. 位图

位图是一种数据结构,类似于数组,在数组中每个下标标识一个元素,而位图使用每个位来标识一种状态

 以上图为例,int类型的整数有32个比特位,每个比特位标识一个元素,一个元素有两种状态(0或1)

接下来我们以一道例题来进一步了解和使用位图:

例题:判断字符是否唯一

题目链接:

 面试题 01.01. 判定字符是否唯一 - 力扣(LeetCode)

题目描述:

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

示例 1:

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

示例 2:

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

限制:

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

思路分析:要判断字符串中是否有字符相同,我们可以使用哈希表来统计每个字符的个数,由于字符串中仅包含小写字母,我们可以使用int类型的数组(int[26])来标识26个小写字母(即0下标位置表示a的个数,1下标位置表示b的个数...),然后统计每个字符的个数。

由于只需要判断是否有字符相同,我们也可以使用位图,使用int类型的变量bitMap来作为“数组”,其中26位来标识26个小写字母,当该字符未出现过时(即对应二进制位为0),将对应二进制位修改为1,而当该字符出现过时(即对应二进制位为1),则可判断有字符相同,返回false

代码实现:

class Solution {public boolean isUnique(String astr) {char[] s = astr.toCharArray();if(s.length > 26) return false;int bitMap = 0;for(char x : s){int index = x - 'a';if((bitMap & (1 << index)) == 0){bitMap |= (1 << index);}else{return false;}}return true;}
}

5. 提取数n的二进制表示中的最右侧的1(lowbit)

要想提取出n中最右侧的1,只需将 n & (-n)

我们可以发现:将 n 转换为 -n(补码) 后,最右侧1 的左边区域(不包括最右侧1)全部变相反,此时,再将n & (-n),就只剩下最右侧的1

6. 去掉数n的二进制表示中的最右侧的1

去掉最右侧的1,只需将 n & (n - 1)

 我们可以发现:将 n 转换为 n-1 后,最右侧1 的右边区域(包括最右侧1)全部变相反,此时,再将n & (n-1),就能够去掉最右侧的1了

我们以一道例题进行练习:

例题:位1的个数

题目链接:

191. 位1的个数 - 力扣(LeetCode)

题目描述:

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

示例 1:

输入:n = 00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。

示例 2:

输入:n = 00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'。

示例 3:

输入:n = 11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'。

思路分析:

题目要求我们计算整数n的二进制表示中的1的个数,可以通过判断每一位是否为1((n >> x) & 1)求出1的个数,但我们知道n & (n-1)能够去掉最右侧的1,因此我们只需计算能够去掉多少个1,即可求出1的个数

代码实现:

public class Solution {// you need to treat n as an unsigned valuepublic int hammingWeight(int n) {int sum = 0;while(n != 0){n = n & (n-1);sum ++;}return sum;}
}

 而题目:

338. 比特位计数 - 力扣(LeetCode)

461. 汉明距离 - 力扣(LeetCode)

也是类似的解题思路,大家可以自行练习

7. 异或(^)运算的运算律

a ^ 0 = a

a ^ a = 0

a ^ b ^ c = a ^ (b ^ c)

我们以一道例题来进一步掌握异或运算的运算律:

例题:只出现一次的数字

题目链接:

136. 只出现一次的数字 - 力扣(LeetCode)

题目描述:

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

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

示例 1 :

输入:nums = [2,2,1]
输出:1

示例 2 :

输入:nums = [4,1,2,1,2]
输出:4

示例 3 :

输入:nums = [1]
输出:1

思路分析:题目告诉我们数组中只有一个元素出现了一次,其他的都出现了两次,且a ^ a = 0,因此我们只需要将数组所有元素异或,出现两次的元素异或后都变为0,最后只剩下出现一次的元素a ^ 0 = a

代码实现:

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

位运算练习

练习1:两整数之和

题目链接:

 371. 两整数之和 - 力扣(LeetCode)

题目描述:

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

示例 1:

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

示例 2:

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

思路分析:不能使用运算符 + 和 - ,则我们可以考虑使用位运算来解决这个问题

异或(^)运算相当于无进位相加,在无进位的情况下(0 + 0 = 0,0 + 1 = 1)

接下来,我们考虑进位的情况:当该位上出现 1 + 1 时,则需要进位(即 1 + 1 = 10)而有需要进位的位为(a & b),进位后为(a & b)<< 1

因此,我们可以考虑将整数a 和 b的和,分为无进位加法的结果和进位结果的和

具体过程为:

以15和9为例:

1.先将每一位相加,且不考虑进位。二进制满2进位,即1 + 1 = 10,此时不考虑进位,因此,可以通过异或实现不考虑进位的相加,即 1 + 1 = 0,0 + 0 = 0,1 + 0 = 1,此时1111 + 1001 = 0110

2.找出进位的数。当出现1 + 1时,产生进位,我们可以通过两个数按位与找到这些存在进位的数,再将其向左移动1位,实现进位

3.将1和2得到的数字相加,由于相加不能使用加法,即重复1、2步骤,模拟实现加法,当进位为0时,即不再产生进位,此时异或的结果即为两个数相加的结果

代码实现:

class Solution {public int getSum(int a, int b) {while(b != 0){int carry = (a & b) << 1;//进位a = a ^ b;//无进位b = carry;}return a;}
}

练习2:只出现一次的数字II

题目链接:

 137. 只出现一次的数字 II - 力扣(LeetCode)

题目描述:

给你一个整数数组 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

思路分析:由于只有一个元素出现了一次,其他n个元素元素都出现了三次,那么对于每一位都有以下四种情况:

1. 3n个0 + 1个0

2. 3n个0 + 1个1

3. 3n个1 + 1个0

4. 3n个1 + 1个1

对其模3(%3)可得:

1. 3n个0 + 1个0  (%3) -> 0

2. 3n个0 + 1个1  (%3) -> 1

3. 3n个1 + 1个0  (%3) -> 0

4. 3n个1 + 1个1  (%3) -> 1

即只出现一次的元素的二进制位,因此,我们只需求出出现一次的元素的每一位,即可求出该元素 

代码实现:

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

练习3:只出现一次的数字III

题目链接:

 260. 只出现一次的数字 III - 力扣(LeetCode)

题目描述:

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

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

示例 1:

输入:nums = [1,2,1,3,2,5]
输出:[3,5]
解释:[5, 3] 也是有效的答案。

示例 2:

输入:nums = [-1,0]
输出:[-1,0]

示例 3:

输入:nums = [0,1]
输出:[1,0]

提示:

  • 2 <= nums.length <= 3 * 104
  • -231 <= nums[i] <= 231 - 1
  • 除两个只出现一次的整数外,nums 中的其他数字都出现两次

思路分析:与只出现一次的数字类似,但此题是两个元素只出现了一次,我们同样可以利用异或的运算律,将所有元素异或,此时得到两个只出现一次的元素的异或结果

如何得到这两个元素呢?

由于这两个元素一定不相同(若相同则异或结果为0,不符合题目中描述),我们可以通过提取结果中最右侧的1(lowbit),并将数组按照该位是否为1分为两组元素,这样,两个只出现一次的数字就被分到了不同的组里,此时再进行异或,就可得到这两个元素

代码实现:

class Solution {public int[] singleNumber(int[] nums) {int ret = nums[0];for(int i = 1; i < nums.length; i++){ret ^= nums[i];}//得到两个数的异或结果int ret1 = ret & (-ret);//找到最低位1int ret2 = 0;for(int i = 0; i < nums.length; i++){if((nums[i] & ret1) == 0){ret2 ^= nums[i];}}ret1 = ret2 ^ ret;return new int[] {ret1, ret2};}
}

练习4:消失的两个数字

题目链接:

 面试题 17.19. 消失的两个数字 - 力扣(LeetCode)

题目描述:

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

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

示例 1:

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

示例 2:

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

提示:

  • nums.length <= 30000

思路分析:

数组中缺失两个数字,设数组的长度为len,则所有元素为1 到 len+2,由于其中缺失两个数字,若将数组中所有元素和1 - len + 2看做一个整体,则此时就变为两个数字只出现一次,其他数字出现两次,此时就和 只出现一次的数字III 相同了,接下来按照 只出现一次的数字III 的解题思路来解题就可以解决该问题

代码实现:

class Solution {public int[] missingTwo(int[] nums) {int len = nums.length;int ret = (len + 2) ^ (len + 1);//求出两个数异或的结果for(int i = 0; i < nums.length; i++){//所有元素异或结果ret ^= nums[i];ret ^= (i+1);}int ret1 = ret & (-ret);//找到最低位1int ret2 = 0;for(int i = 0; i < len; i++){if((nums[i] & ret1) == 0){ret2 ^= nums[i];}}for(int i = 1; i <= len + 2; i++){if((i & ret1) == 0){ret2 ^= i;}}ret1 = ret2 ^ ret;return new int[] {ret1, ret2};}
}

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

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

相关文章

《区块链公链数据分析简易速速上手小册》第5章:高级数据分析技术(2024 最新版)

文章目录 5.1 跨链交易分析5.1.1 基础知识5.1.2 重点案例&#xff1a;分析以太坊到 BSC 的跨链交易理论步骤和工具准备Python 代码示例构思步骤1: 设置环境和获取合约信息步骤2: 分析以太坊上的锁定交易步骤3: 跟踪BSC上的铸币交易 结论 5.1.3 拓展案例 1&#xff1a;使用 Pyth…

OCP的operator——(2)OLM

文章目录 了解OperatorOperator Lifecycle Manager&#xff08;OLM&#xff09;OLM概念和资源OLM是什么OLM资源Cluster service version&#xff08;CSV&#xff09;Catalog source定制catalog source的image模板目录健康需求 SubscriptionInstall planOperator groupOperator …

SQL世界之命令语句Ⅴ

目录 一、SQL CREATE INDEX 语句 1.SQL CREATE INDEX 语句 2.SQL CREATE INDEX 语法 3.SQL CREATE UNIQUE INDEX 语法 4.SQL CREATE INDEX 实例 二、SQL 撤销索引、表以及数据库 1.SQL DROP INDEX 语句 2.SQL DROP TABLE 语句 3.SQL DROP DATABASE 语句 4.SQL TRUNCA…

文件压缩炸弹,想到有点后怕

今天了解到一个概念&#xff0c;压缩炸弹。 参考&#xff1a; https://juejin.cn/post/7289667869557178404 https://www.zhihu.com/zvideo/1329374649210302464 什么是压缩炸弹 压缩炸弹&#xff08;也称为压缩文件炸弹、炸弹文件&#xff09;是一种特殊的文件&#xff0c;它…

ACTable开源框架的使用及异常

介绍 ACTable是对Mybatis做的增强功能&#xff0c;支持SpringBoot以及传统的SpringMvc架构&#xff0c;配置简单&#xff0c;使用方便。主要是自动生成数据库表&#xff0c;直接修改java代码&#xff0c;数据库就会对应的变化&#xff0c;省去在调整数据库表的问题&#xff0c…

笔试刷题(持续更新)| Leetcode 45,1190

45. 跳跃游戏 题目链接&#xff1a; 45. 跳跃游戏 II - 力扣&#xff08;LeetCode&#xff09; 这道题思路不难记&#xff0c;遍历数组每个位置&#xff0c;更新下一次的范围&#xff0c;当当前位置已经在当前范围之外时&#xff0c;步数一定得加一&#xff0c;当前范围更新成…

蓝桥杯官网填空题(质数拆分)

问题描述 将 2022 拆分成不同的质数的和&#xff0c;请问最多拆分成几个&#xff1f; 答案提交 本题为一道结果填空的题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将结果输出即可。 运行限制 import java.util.Scanner;public class Main {static int …

Pandas Series 的学习笔记

Pandas Series 的学习笔记 0. Pandas 简介1. Series 学习1-1. 创建 Series1-2. 索引1-3. 选择数据1-4. 修改 Series1-5. Series 的操作 2. 结论 0. Pandas 简介 想象一下&#xff0c;你有一张超级大的餐桌&#xff0c;上面放满了各种各样的食物。Pandas 就像是这张餐桌&#x…

面试:大数据和深度学习之间的关系是什么?

大数据与深度学习之间存在着紧密的相互关系&#xff0c;它们在当今技术发展中相辅相成。 大数据的定义与特点:大数据指的是规模(数据量)、多样性(数据类型)和速度(数据生成及处理速度)都超出了传统数据处理软件和硬件能力范围的数据集。它具有四个主要特点&#xff0c;通常被称…

【Java】零基础蓝桥杯算法学习——二分查找

算法模板一: // 数组arr的区间[0,left-1]满足arr[i]<k,[left,n-1]满足arr[i]>k;Scanner scan new Scanner(System.in);int[] arr {1,2,3,4,5};int left 0,right arr.length-1;int k scan.nextInt();while(left<right) {//leftright时退出循环int mid (leftrigh…

leetcode(双指针)11.盛最多水的容器(C++详细解释)DAY9

文章目录 1.题目示例提示 2.解答思路3.实现代码结果 4.总结 1.题目 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回…

【Django】Django项目部署

项目部署 1 基本概念 项目部署是指在软件开发完毕后&#xff0c;将开发机器上运行的软件实际安装到服务器上进行长期运行。 在安装机器上安装和配置同版本的环境[python&#xff0c;数据库等] django项目迁移 scp /home/euansu/Code/Python/website euansuxx.xx.xx.xx:/home…

Rust的Match语句:强大的控制流运算符

在Rust中&#xff0c;match语句是一种强大的控制流运算符&#xff0c;用于比较一个值与一系列模式&#xff0c;并执行与第一个匹配的模式对应的代码块。它提供了一种清晰而灵活的方式来处理多个条件&#xff0c;使得代码更加可读、易于理解。 Match语句的基本使用 首先&#…

2月14作业

21.C 22.D 23.B 5先出栈表示1&#xff0c;2&#xff0c;3&#xff0c;4已经入栈了&#xff0c;5出后4出&#xff0c;但之后想出1得先让3&#xff0c;2先后出栈&#xff0c;所以 B 不可能 24.10&#xff0c;12&#xff0c;120 25.2&#xff0c;5 26.可能会出现段错误…

js importmap

在html文件中使用npm 下载的包&#xff0c;比如vue&#xff0c;在使用import引入的时候会报错 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-widt…

vue使用Mars3d弹框嵌套video视频/实时视频(flv) 使用jessibuca.js播放器

在html引入jessibuca.js (还需下载decoder.js&#xff0c;decoder.wasm) http://jessibuca.monibuca.com/player.html 官方下载 <script type"text/javascript" src"./jessibuca.js"></script> 同Mars3d弹框嵌套视频播放m3u8前面相同 1.播放…

OpenCV基础:用Python生成一幅随机的噪声图像

使用Python&#xff1a;生成一幅随机数值的灰度图像&#xff0c;图像大小为1616像素。借助OpenCV库。输出数值&#xff0c;并显示图像。 # -*- coding: utf-8 -*- """ Created on Wed Feb 14 21:49:09 2024author: 李立宗公众号&#xff1a;计算机视觉之光知识…

SQL世界之命令语句Ⅱ

目录 一、SQL TOP语句 1.TOP 子句 2.SQL TOP 实例 3.SQL TOP PERCENT 实例 二、SQL LIKE 操作符 1.LIKE 操作符 2.SQL LIKE 操作符语法 3.LIKE 操作符实例 三、SQL通配符 1.SQL 通配符 2.使用 % 通配符 3.使用 _ 通配符 4.使用 [charlist] 通配符 四、SQL IN操作…

Raspbian简易RTSP服务

Raspbian简易RTSP服务 1. 源由2. 搭建简易RTSP服务器2.1 系统安装2.2 软件安装2.3 命令介绍2.3.1 libcamera-hello2.3.2 libcamera-vid2.3.3 cvlc 3. 实测4. 参考资料 1. 源由 鉴于前期的一些准备工作&#xff1a; 《ArduPilot开源飞控之Companion Computers简单分析》《Ardu…

Python re找到特定pattern并将此pattern重复n次

要找到字符串s中的数字&#xff0c;并将这些数字重复3次&#xff1a; import re s "abc123def456ghi789" # 找到所有的数字 numbers re.findall(r\d, s) # 重复每个数字3次 repeated_numbers [num * 3 for num in numbers] # 将重复的数字放回原位置 #…