关于位操作和掩码(字符串查重)
目录
关于位操作和掩码(字符串查重)
0.1 背景
今天在 “力扣cn” 做了一道给字符串查重的题。
我的做法:
- 逐个字符地,把字符串转换成 HashSet(利用HashSet中元素不重复的特性)。
- 比较 “原字符串” 和 “HashSet” 的长度:
- 如果相同,说明没有重复;
- 如果不同,说明重复了。
|
|
比起用暴力双循环是好很多,自己还挺满意的,做完题看看解析,又发现了新天地:
- 虽然这样做,也能通过,而且执行效率排名还挺高;
- 但是,这其实并不是题目最初设计的考点,或者说还有更好的解法。
0.2 位移运算、位运算 和 掩码
这个解法还有一个重要前提,就是“只使用小写字母”(全大写字母也行。 “力扣cn” 在搬运的时候,忘了把这点加上)。
当我弄明白这个解法的时候,就像第一次写出 Hello World 时一样兴奋😮
|
|
可以把结果集理解为一个与 “a ~ z” 按顺序对应的布尔类型的数组 boolean[]
,有助于理解。
0.3 再谈前提
然后我们再回头看这个重要前提,真实的限制,其实是 “字符串中,使用的字符,其 ASCII 码必须连续,且字符种类不能超过32”(但这样出题就太暴露意图了)。
如果使用33个连续字符,比如用 “ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a” 进行测试,会得到 false 的结果。
原因是:由于溢出,a
使用了和 A
一样的掩码位,于是被程序判为重复。
所以,如果换成 long 类型,就可以支持到 64 种ASCII码连续的字符(然并卵)。
0.4 举一反三
这里其实用到一个很重要的概念:掩码
其实很多地方都会用到,比如:
- 数通网络里的 “子网掩码” 1,如果学过这块,理解起来应该更得心应手。
- Linux 文件夹权限也用到了掩码2。
- 这篇文章做了不错的拓展3:3鼠8瓶问题,和应用的权限控制(去年我写一个PHP项目的时候有类似想法,现在更通透了)。
位操作真是不简单,这是我第二次被位操作惊艳到了,上一次是 “不使用中间变量,交换两个变量的值”(我知道用加法,但不知道可以用位异或)。