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

12.位运算的性质(异或的性质)

文章目录


& ; 或 | ; 异或 ^

异或的性质

如果 a ^ b = c 成立,那么a ^ c = bb ^ c = a 均成立。即 如果有三个数,满足其中两个数的异或值等于另一个值,那么这三个数的顺序可以任意调换

  • 说明:利用这条性质,可以不使用第 3 个变量而交换两个变量的值。

异或运算可以看作 「二进制下不进位的加法」,所以常常用来解决一些和奇偶性相关的问题

求异或和问题

421. 数组中两个数的最大异或值

中等

给你一个整数数组 nums ,返回 nums[i] XOR nums[j] 的最大运算结果,其中 0 ≤ i ≤ j < n

示例 1:

输入:nums = [3,10,5,25,2,8]
输出:28
解释:最大运算结果是 5 XOR 25 = 28.

示例 2:

输入:nums = [14,70,53,83,49,91,36,80,92,51,66,70]
输出:127

提示:

  • 1 <= nums.length <= 2 * 105
  • 0 <= nums[i] <= 231 - 1

https://leetcode.cn/problems/maximum-xor-of-two-numbers-in-an-array/solutions/2511644/tu-jie-jian-ji-gao-xiao-yi-tu-miao-dong-1427d/

异或性质、假设修正

class Solution {// 把 nums数组的数转成二进制来思考,看最高位、次高位..。能不能是1?// 如果 a ^ b = max 成立,那么一定有 max ^ b = a 成立// 因此假设 max 的数位i 可以为1,然后//        问题转化为两数之和,用哈希表记录遍历结果,求max^b=a是否存在public int findMaximumXOR(int[] nums) {int max = 0;for(int x : nums) max = Math.max(max, x);// 得到为1的最高比特位int highBit = 31 - Integer.numberOfLeadingZeros(max);int ans = 0, mask = 0;Set<Integer> seen = new HashSet();for(int i = highBit; i >= 0; i--){ // 从最高比特位开始枚举seen.clear();mask |= 1 << i; // 将[hightbit,i]位置都变为1int newAns = ans | (1 << i); // 假定第 i 位可以为1for(int x : nums){x &= mask; // 保留前缀,低于 i 的比特位置为 0if(seen.contains(newAns ^ x)){ans = newAns; // 这个bit位可以时1break;}seen.add(x);}}return ans;}
}

2935. 找出强数对的最大异或值 II

困难

给你一个下标从 0 开始的整数数组 nums 。如果一对整数 xy 满足以下条件,则称其为 强数对

  • |x - y| <= min(x, y)

你需要从 nums 中选出两个整数,且满足:这两个整数可以形成一个强数对,并且它们的按位异或(XOR)值是在该数组所有强数对中的 最大值

返回数组 nums 所有可能的强数对中的 最大 异或值。

注意,你可以选择同一个整数两次来形成一个强数对。

示例 1:

输入:nums = [1,2,3,4,5]
输出:7
解释:数组 nums 中有 11 个强数对:(1, 1), (1, 2), (2, 2), (2, 3), (2, 4), (3, 3), (3, 4), (3, 5), (4, 4), (4, 5) 和 (5, 5) 。
这些强数对中的最大异或值是 3 XOR 4 = 7 。

示例 2:

输入:nums = [10,100]
输出:0
解释:数组 nums 中有 2 个强数对:(10, 10) 和 (100, 100) 。
这些强数对中的最大异或值是 10 XOR 10 = 0 ,数对 (100, 100) 的异或值也是 100 XOR 100 = 0 。

示例 3:

输入:nums = [500,520,2500,3000]
输出:1020
解释:数组 nums 中有 6 个强数对:(500, 500), (500, 520), (520, 520), (2500, 2500), (2500, 3000) 和 (3000, 3000) 。
这些强数对中的最大异或值是 500 XOR 520 = 1020 ;另一个异或值非零的数对是 (5, 6) ,其异或值是 2500 XOR 3000 = 636 。

提示:

  • 1 <= nums.length <= 5 * 104
  • 1 <= nums[i] <= 220 - 1
class Solution {public int maximumStrongPairXor(int[] nums) {Arrays.sort(nums);int highBit = 31 - Integer.numberOfLeadingZeros(nums[nums.length - 1]);int ans = 0, mask = 0;Map<Integer, Integer> mp = new HashMap<>();for (int i = highBit; i >= 0; i--) { // 从最高位开始枚举mp.clear();mask |= 1 << i;int newAns = ans | (1 << i); // 这个比特位可以是 1 吗?for (int y : nums) {int maskY = y & mask; // 低于 i 的比特位置为 0if (mp.containsKey(newAns ^ maskY) && mp.get(newAns ^ maskY) * 2 >= y) {ans = newAns; // 这个比特位可以是 1break;}mp.put(maskY, y);}}return ans;}
}

异或前缀和问题(最…回文串、串字符出现奇/偶次)

参考:一步步优化!从前缀和到前缀异或和(附题单!)https://leetcode.cn/problems/can-make-palindrome-from-substring/solution/yi-bu-bu-you-hua-cong-qian-zhui-he-dao-q-yh5p/

注意,使用两数之和方法最后会求字串的长度和个数

  • 求长度:mapvaluesum[i]第一次出现的位置
  • 求个数:mapvaluesum[i]出现的次数

1371. 每个元音包含偶数次的最长子字符串

中等

给你一个字符串 s ,请你返回满足以下条件的最长子字符串的长度:每个元音字母,即 ‘a’,‘e’,‘i’,‘o’,‘u’ ,在子字符串中都恰好出现了偶数次。

示例 1:

输入:s = "eleetminicoworoep"
输出:13
解释:最长子字符串是 "leetminicowor" ,它包含 e,i,o 各 2 个,以及 0 个 a,u 。

示例 2:

输入:s = "leetcodeisgreat"
输出:5
解释:最长子字符串是 "leetc" ,其中包含 2 个 e 。

示例 3:

输入:s = "bcbcbc"
输出:6
解释:这个示例中,字符串 "bcbcbc" 本身就是最长的,因为所有的元音 a,e,i,o,u 都出现了 0 次。

提示:

  • 1 <= s.length <= 5 x 10^5
  • s 只包含小写英文字母。
class Solution {public int findTheLongestSubstring(String s) {int n = s.length();// 用 bit位 标识对应字母奇偶性// sum[i] 标识 s[0:i) 的子串中每种字母出现次数的奇偶性int[] sum = new int[n+1];for(int i = 0; i < n; i++){int bit = 0;// 每个元音字母,即 'a','e','i','o','u' ,在子字符串中都恰好出现了偶数次。if(check(s.charAt(i)))bit = 1 << (s.charAt(i) - 'a');sum[i+1] = sum[i] ^ bit; }int res = 0;// 问题化为两数之和  a ^ b = 0Map<Integer, Integer> map = new HashMap<>();for(int i = 0; i <= n; i++){// 注意求最长串长度,map中只保存sum第一次出现位置if(map.containsKey(sum[i]))res = Math.max(res, i - map.get(sum[i]));elsemap.put(sum[i], i);}return res;}public boolean check(Character c){return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';}
}

1542. 找出最长的超赞子字符串「求长度」

困难

给你一个字符串 s 。请返回 s 中最长的 超赞子字符串 的长度。

「超赞子字符串」需满足满足下述两个条件:

  • 该字符串是 s 的一个非空子字符串
  • 进行任意次数的字符交换后,该字符串可以变成一个回文字符串

示例 1:

输入:s = "3242415"
输出:5
解释:"24241" 是最长的超赞子字符串,交换其中的字符后,可以得到回文 "24142"

示例 2:

输入:s = "12345678"
输出:1

示例 3:

输入:s = "213123"
输出:6
解释:"213123" 是最长的超赞子字符串,交换其中的字符后,可以得到回文 "231132"

示例 4:

输入:s = "00"
输出:2

提示:

  • 1 <= s.length <= 10^5
  • s 仅由数字组成
class Solution {/**进行任意次数的字符交换后,该字符串可以变成一个回文字符串 ==> 字符串「不同字符出现次数」为奇数的个数 <= 1*/public int longestAwesome(String s) {int n = s.length();int[] sum = new int[n+1];for(int i = 0; i < n; i++){int bit = 1 << (s.charAt(i) - '0');sum[i+1] = sum[i] ^ bit;}int res = 0;// 问题转化为两数之和 // a ^ b = 1 / 10 / 100 / 1000...Map<Integer, Integer> map = new HashMap<>();for(int i = 0; i <= n; i++){// 字符串「不同字符出现次数」为奇数的个数 = 0if(map.containsKey(sum[i]))res = Math.max(res, i - map.get(sum[i]));// 字符串「不同字符出现次数」为奇数的个数 = 1for(int j = 0; j < 10; j++){int target = (1 << j);// a ^ b == target ==> a = target ^ bif(map.containsKey(target ^ sum[i]))res = Math.max(res, i - map.get(target ^ sum[i]));}// 注意求最长串长度,map中只保存sum第一次出现位置if(!map.containsKey(sum[i]))map.put(sum[i], i);}return res;}
}

1915. 最美子字符串的数目「求个数」

中等

如果某个字符串中 至多一个 字母出现 奇数 次,则称其为 最美 字符串。

  • 例如,"ccjjc""abab" 都是最美字符串,但 "ab" 不是。

给你一个字符串 word ,该字符串由前十个小写英文字母组成('a''j')。请你返回 word最美非空子字符串 的数目*。如果同样的子字符串在 word 中出现多次,那么应当对 每次出现 分别计数。*

子字符串 是字符串中的一个连续字符序列。

示例 1:

输入:word = "aba"
输出:4
解释:4 个最美子字符串如下所示:
- "aba" -> "a"
- "aba" -> "b"
- "aba" -> "a"
- "aba" -> "aba"

示例 2:

输入:word = "aabb"
输出:9
解释:9 个最美子字符串如下所示:
- "aabb" -> "a"
- "aabb" -> "aa"
- "aabb" -> "aab"
- "aabb" -> "aabb"
- "aabb" -> "a"
- "aabb" -> "abb"
- "aabb" -> "b"
- "aabb" -> "bb"
- "aabb" -> "b"

示例 3:

输入:word = "he"
输出:2
解释:2 个最美子字符串如下所示:
- "he" -> "h"
- "he" -> "e"

提示:

  • 1 <= word.length <= 105
  • word 由从 'a''j' 的小写英文字母组成
class Solution {public long wonderfulSubstrings(String word) {int n = word.length();int[] sum = new int[n+1];for(int i = 0; i < n; i++){int bit = (1 << (word.charAt(i) - 'a'));sum[i+1] = sum[i] ^ bit;}long res = 0;Map<Integer, Integer> map = new HashMap<>();// 某个字符串中 至多一个 字母出现 奇数 次for(int i = 0; i <= n; i++){if(map.containsKey(sum[i]))res += map.get(sum[i]);for(int j = 0; j < 11; j++){int target = (1 << j);if(map.containsKey(target ^ sum[i]))res += map.get(target ^ sum[i]);}map.merge(sum[i], 1, Integer::sum);}return res;}
}
http://www.lryc.cn/news/241464.html

相关文章:

  • 国标直流充电枪9孔分别啥意思?
  • 关于 Google AMP 和 SEO
  • 【SpringMVC】 对请求的不同响应
  • SQL进阶学习
  • 邦芒解析:做好职场规划防止跳槽失败
  • 基于springboot实现实习管理系统的设计与实现项目【项目源码+论文说明】计算机毕业设计
  • 【华为OD题库-031】比赛的冠亚季军-java
  • 电脑如何禁止截屏
  • 【Web】NewStarCTF Week1 个人复现
  • Android 提示框代码 java语言
  • 【c语言】二维数组的对角线对称交换
  • Sulfo-CY3 NHS荧光染料的制备和表征
  • 数字乡村:科技赋能农村产业升级
  • K8S部署mongodb-sharded-cluster(7.0.2)副本分片
  • Dockerfile-CentOS7.9+Python3.11.2
  • 自定义责任链Filter实现
  • NX二次开发UF_CSYS_create_matrix 函数介绍
  • css引入的三种方式
  • 含羞草研究所研究含羞草的代码
  • 常见立体几何图形的体积
  • vue3 + vue-router + keep-alive缓存页面
  • unigui同页面内重定向跳转,企业微信内部应用开发获取用户code例子
  • 垃圾数据啊
  • GB/T 29498-2013 木门窗检测
  • rocketMQ5.0顺序消息golang接入
  • HuggingFace-利用BERT预训练模型实现中文情感分类(下游任务)
  • PSP - 从头搭建 抗原类别 (GPCR) 的 蛋白质结构预测 项目流程
  • 城市NOA加速落地,景联文科技高质量数据标注助力感知系统升级
  • 控制反转(IoC)是什么?
  • Redisson分布式锁源码解析、集群环境存在的问题