我爱学算法之—— 位运算(中)
一、判定字符是否唯一
题目解析
对于这道题,给的一个字符串,要求我们判断该字符串中的所有字符是否完全都不同;
如果存在相同字符,就返回false
;否则就返回true
其中字符串s
中只存在小写字母。
算法思路
解法一:
使用
hash
(set
/unordered_set
)统计字符串s
中的每一个字符,当出现相同字符就返回false
;遍历完
s
,还是没有出现相同字符就返回true
。
解法二:
题目中也提到:如果不使用额外的数据结构,会很加分。
这里我们也可以不使用额外的数据结构,当然不是使用数组来统计每个字符。
字符串
s
中,只存在小写字母(26
个小写字母);并且我们只需判断是否存在相同的字母即可。所以,这里就可以使用位图来统计每个小写字母是否存在。
- 遍历字符
s
,判断字符e
是否存在- 判断位图
bitmap
中,二进制第e-'a'
位是否为1
;- 为
1
则表示该字符已经出现过;不为1
则表示该字符之前没有出现过,将要将第e-'a'
位修改为1
。
代码实现
class Solution {
public:bool isUnique(string astr) {int bitmap = 0;for (auto& e : astr) {int i = e - 'a';// 判断第i位是否为1int tmp = bitmap;if (((tmp >> i) & 1) == 1)return false;elsebitmap |= (1 << i);}return true;}
};
二、丢失的数字
题目解析
对于这道题,给定一个包含[0 , n]
中n
个数的数组nums
,要求找出数组nums
中,[0 , n]
范围内没有出现的数字。
简单来说就是:[0 , n]
中 一共n+1
个数,在数组中nums
只存在n
个,要找出nums
中不存在的那一个数。
算法思路
这道题要直接去找这个不存在的数,使用hash
统计还是非常麻烦的;
思路:
数组
nums
中,一个存在n
个数,[0 , n]
中的n
个数(每个数出现一次);而数组下标范围:
[0 , n-1]
(0
到n-1
,n
个数,每个数出现一次);如果再增加一个数
n
,那在nums
中(包含下标),[0 , n]
中只有一个数只出现了一次,其他数都出现了两次。问题就转化为:只出现一次的数字
所以,只需让n
按位与上数组下标[0 , n]
和数组nums
中的每一个数;即可找出这一个丢失的数字。
代码实现
class Solution {
public:int missingNumber(vector<int>& nums) {int n = nums.size();int ret = n;for (int i = 0; i < n; i++) {ret ^= i;ret ^= nums[i];}return ret;}
};
三、两整数之和
题目解析
这道题很简单,题如其名:给定两个整数,不使用运算符+
/-
,计算并返回两整数之和。
算法思路
这道题,如果不讲武德,直接就返回a + b
,就太没有意思了。
这里我们可以使用位运算^
和&
操作来计算a+b
:
^
按位与操作,也就相等于无进位相加,要使用位运算来计算a+b
,也就只用考虑进位问题了
^
:无进位相加进位:只有
a
和b
对应bit
位都为1
时才会产生进位;(而进位是要加到高位去的(a&b) << 1
)有了无进位相加
a^b
、进位(a&b) << 1
,就要计算a^b
+(a&b) << 1
,就又要计算无进位相加和进位,并计算和。直到进位为
0
,才计算完毕。
代码实现
class Solution {
public:int getSum(int a, int b) {int ret = a ^ b;int carry = (a & b) << 1;while (carry != 0) {a = ret;b = carry;ret = a ^ b;carry = (a & b) << 1;}return ret;}
};
本篇文章到这里就结束了,感谢支持
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws