文章目录
一、位运算符
运算符 | 功能 | 用法 | 解释 |
---|---|---|---|
& | 位与 | a&b | 相当于为二进制各位按位相乘,除1&1 = 1 其他均为0 |
| | 位或 | a|b | 两个操作数只要有一个为1则结果为1,即,除了0|0 = 0,其余均为1 |
^ | 位异或 | a^b | 结果为二进制各位按位相乘,除1&1 = 1 其他均为0 |
<< | 左移 | a<<b | 相当于a × 2b |
>> | 右移 | a>>b | 相当于a / 2b,并将小数部分舍去 |
~ | 位求反 | ~a | 整数a的二进制的每一位0变成1,1变成0 |
二、位运算应用
并集
:A | B
交集
:A & B
全集
:( 1 << n ) - 1
补集
:( ( 1 << n ) - 1 ) ^ A
A 是否是 B 的子集
:(A & B) == B
判断 n 是否是 2 的幂
:n & (n - 1) == 0
将 n 最低位的 1 变为 0
:n &= (n - 1)
三、例题
3.1 LeetCode 136. 只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
解题:
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ans = 0;
//根据交换律,例如1 ^ 2 ^ 1 = 1 ^ 1 ^ 2 = 0 ^ 2 = 2
for(int i : nums) ans ^= i;
return ans;
}
};
3.2 LeetCode 191. 位1的个数
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。
提示:
请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在上面的 示例 3 中,输入表示有符号整数 -3。
示例 1:
输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。
示例 2:
输入:00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'。
示例 3:
输入:11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'。
解题:
class Solution {
public:
int hammingWeight(uint32_t n) {
int ans = 0;
while(n != 0){
//将n最低位的1变为0
n &= (n - 1);
ans++;
}
return ans;
}
};
3.3 LeetCode 1763. 最长的美好子字符串
当一个字符串 s 包含的每一种字母的大写和小写形式 同时 出现在 s 中,就称这个字符串 s 是 美好 字符串。比方说,“abABB” 是美好字符串,因为 ‘A’ 和 ‘a’ 同时出现了,且 ‘B’ 和 ‘b’ 也同时出现了。然而,“abA” 不是美好字符串因为 ‘b’ 出现了,而 ‘B’ 没有出现。
给你一个字符串 s ,请你返回 s 最长的 美好子字符串 。如果有多个答案,请你返回 最早 出现的一个。如果不存在美好子字符串,请你返回一个空字符串。
示例 1:
输入:s = “YazaAay”
输出:“aAa”
解释:“aAa” 是一个美好字符串,因为这个子串中仅含一种字母,其小写形式 ‘a’ 和大写形式 ‘A’ 也同时出现了。
“aAa” 是最长的美好子字符串。
示例 2:
输入:s = “Bb”
输出:“Bb”
解释:“Bb” 是美好字符串,因为 ‘B’ 和 ‘b’ 都出现了。整个字符串也是原字符串的子字符串。
示例 3:
输入:s = “c”
输出:""
解释:没有美好子字符串。
示例 4:
输入:s = “dDzeE”
输出:“dD”
解释:“dD” 和 “eE” 都是最长美好子字符串。
由于有多个美好子字符串,返回 “dD” ,因为它出现得最早。
提示:
1 <= s.length <= 100
s 只包含大写和小写英文字母。
解题:
class Solution {
public:
string longestNiceSubstring(string s) {
int n = s.size();
int pos = 0;
int len = 0;
for(int i = 0; i < n; i++){
int lower = 0;
int upper = 0;
for(int j = i; j < n; j++){
if(islower(s[j])){
//将小写字母用二进制进行标记
lower |= 1 << (s[j] - 'a');
}else{
upper |= 1 << (s[j] - 'A');
}
//如果小写字母与大写字母的二进制标记相同,
//则说明此子串满足没好子字符串的条件
if(lower == upper && j - i + 1 > len){
pos = i;
len = j - i + 1;
}
}
}
return s.substr(pos, len);
}
};