目录
前言:
两整数之和
题目解析
算法原理
算法编写
只出现一次的数字II
题目解析
算法原理
算法编写
前言:
本文的主题是位运算,通过两道题目讲解,一道是只出现一次的数字II,一道是两整数之和。
链接分别为:
137. 只出现一次的数字 II - 力扣(LeetCode)
371. 两整数之和 - 力扣(LeetCode)
题目分为三个部分讲解,一是题目解析,二是算法原理,三是算法编写,那么,话不多说,直接进行主题咯。
两整数之和
题目解析
题目的意思是非常明确的,就是让我们不适用+ - 运算符计算两个整数相加,那么在类和对象章节我们介绍了可能使用静态成员变量的方法来操作,这里我们介绍使用的异或运算来操作。
算法原理
对于异或来说,我们的另一种记忆方式是无进位相加,所以我们能够使用异或求得0 + 1, 0 + 0,那么对于额外的操作就是要求1 + 1,那么1 + 1是进位了,对于&操作可以完美的完成我们对于进位的需求,但是进位是往前进位,所以我们需要左移,当进位为0的时候,我们就成功求到了所需要的元素。
算法编写
class Solution {
public:
int getSum(int a, int b)
{
while(b)
{
int x = a ^ b;
int carry = (a & b) << 1;
a = x;
b = carry;
}
return a;
}
};
有的时候如果说发生了溢出,就是因为异或之和x为-1,此时左移肯定不大行,操作是将carry的类型定义为unsigned就可以了。
只出现一次的数字II
题目解析
对于这道题目,要求是让我们找到一大堆数字中只出现过一次的数字,对于只出现一次的数字I和只出现一次的数字III,重复的数字都是重复出现了2次,或者是说找两个重复的数字,但是对于这道题目,它重复出现的数字是重复了3次,就相对来说麻烦一点,题目的要求我们清楚了,直接进入到算法原理吧。
算法原理
虽然说是使用的异或运算,但是这里我们不妨列出一个规律:
由于整个数组中,需要找的元素只出现了「⼀次」,其余的数都出现的「三次」,因此我们可以根 据所有数的「某⼀个⽐特位」的总和 %3 的结果,快速定位到 0 还是 1,所以我们可以通过修改每个bit位上的值,将原来的数字还原出来。
算法编写
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ret = 0;
for (int i = 0; i < 32; i++) {
int sum = 0;
for (int x : nums)
if (((x >> i) & 1) == 1)
sum++;
sum %= 3;
if (sum == 1)
ret |= 1 << i;
}
return ret;
}
};
感谢阅读!