我爱学算法之—— 位运算(下)
一、只出现一次的数字 II
题目解析
给定一个数组nums
,其中只有一个元素出现了一次,其余的每个元素都出现了三次。
要求找出这个只出现一次的元素,并返回。
算法思路
对于这道题,可以使用hash
记录每一个元素出现的次数,然后再找到出现一次的元素并返回。
但是题目题目要求:线性时间复杂度O(n)
、常数级空间复杂度O(1)
思路:位运算
这里数组nums
中所有的元素都出现了奇数次,这里就不能使用a ^ a = 0
、a ^ 0 = a
来进行获取;
这里,就要关注
int
(一个数)的每一个bit
位;对于一个
bit
位,一个数x
只出现了一次,其他每一个元素都出现了三次;这里就只需要将每一个
bit
位上的数加起来,再对其%3
。((3n + x) % 3 = x
)无论出现三次的元素该
bit
位为0
还是1
,所有元素该bit
位的和%3
的结果就是只出现一次的元素的该bit
位的值。所以,只需统计
nums
中所有元素每一个bit
位的和,再%3
就可获得只出现一次的数该bit
位的值。得到了该数每一个
bit
位的值,再获取该数然后返回即可。
代码实现
class Solution {
public:int singleNumber(vector<int>& nums) {int ret = 0;for (int i = 0; i < 32; i++) {int sum = 0;for (auto& e : nums) {if ((e >> i) & 1)sum++;}sum %= 3;if (sum == 1)ret |= (1 << i);}return ret;}
};
二、消失的两个数字
题目解析
这道题,给定一个数组,该数组中包含[1 , N]
中所有的整数,但是缺少了两个数字。(N-2
个)
要我们求出缺失的两位数字;
题目要求:时间复杂度:O(n)
、空间复杂度O(1)
。
算法思路
思路一:
对于这道题,我们可以使用
hash
表统计nums
数组中出现的元素,然后找到没有出现的两个数字然后返回即可。空间复杂度:
O(n)
。
思路二:
在做这道题之前,如果了解过丢失的数字 和 只出现一次的数字 III就会非常简单;
思路:
- 异或
nums
中的所有数和1-N
中所有数(除了丢失的两个数字,其他所有数都出现了两次);这样就获得了a^b
。- 根据
a^b
,获取最低位的1
。- 再将
nums
中所有数和1-N
中所有数分为两组分别进行异或,即可获取a
和b
。
代码实现
class Solution {
public:vector<int> missingTwo(vector<int>& nums) {int n = nums.size();int tmp = 0;for (int i = 0; i < n; i++)tmp ^= nums[i];for (int i = 1; i <= n + 2; i++)tmp ^= i;int lowbit = tmp & (-tmp);int a = 0, b = 0;for (int i = 0; i < n; i++) {if (lowbit & nums[i])a ^= nums[i];elseb ^= nums[i];}for (int i = 1; i <= n + 2; i++) {if (lowbit & i)a ^= i;elseb ^= i;}return {a, b};}
};
本篇文章到这里就结束了,感谢支持
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws