0%

位运算合集

136. 只出现一次的数字

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

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

示例 :

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

C++

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

// 交换律:a ^ b ^ c <=> a ^ c ^ b
// 任何数与0异或不变 0 ^ n => n
// 相同的数异或为0 n ^ n => 0

// var a = [2,3,2,4,4]
// 2 ^ 3 ^ 2 ^ 4 ^ 4等价于 2 ^ 2 ^ 4 ^ 4 ^ 3 => 0 ^ 0 ^3 => 3

268. 丢失的数字

给定一个包含 [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 中的所有数字都 独一无二

进阶:你能否实现线性时间复杂度、仅使用额外常数空间的算法解决此问题?

C++

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

191. 位1的个数

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

提示:

  • 请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
  • 在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在上面的 示例 3 中,输入表示有符号整数 -3

示例 :

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

C++

image-20230207185015323

class Solution {
public:
int hammingWeight(uint32_t n) {
int res = 0;
while(n){
n &= n - 1;
res ++;
}
return res;
}
};

338. 比特位计数

给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。

示例 1:

输入:n = 2
输出:[0,1,1]
解释:
0 --> 0
1 --> 1
2 --> 10

示例 2:

输入:n = 5
输出:[0,1,1,2,1,2]
解释:
0 --> 0
1 --> 1
2 --> 10
3 --> 11
4 --> 100
5 --> 101

提示:

  • 0 <= n <= 105

进阶:

  • 很容易就能实现时间复杂度为 O(n log n) 的解决方案,你可以在线性时间复杂度 O(n) 内用一趟扫描解决此问题吗?
  • 你能不使用任何内置函数解决此问题吗?(如,C++ 中的 __builtin_popcount

C++

法一(去的不一定是0)

i >> 1会把最低位去掉

n&1
n为奇数时,n&1的结果就是1 二进制n的最低位为1
n为偶数时,n&1的结果就是0 二进制n的最低位为0

class Solution {
public:
vector<int> countBits(int n) {
vector<int> res(n + 1, 0);
for(int i = 1; i <=n; i++)
res[i] = res[i >> 1] + (1 & i);
return res;
}
};
法二(去的肯定是0)

image-20230207185015323

class Solution {
public:
vector<int> countBits(int n) {
vector<int> res(n + 1, 0);
for(int i = 1; i <=n; i++)
res[i] = res[i &(i - 1)] + 1;
return res;
}
};