力扣每日一题之位运算的应用
给你一个字符串 s
,将该字符串中的大写字母转换成相同的小写字母,返回新的字符串。
当然我们可以用库函数解决这个问题,但是如果这个问题出现在面试里,那肯定是不能用库函数的。
这里我们使用位运算解决这个大小写转换问题。
我们知道
大写字母A-Z的ASCII码是65到90,小写字母的ASCII码是97到112,大小写字母的ASCII码相差32;
大写A(65)的二进制编码为1000001,小写a(97)的二进制编码位1100001。
从上面我们可以发现一个规律:
- 大小写是由第五位是1还是0来区分的。
1 | func main() { |
问题转化为:如何让一个二进制的某一位的值发生改变?
- 如果需要从0变成1,只需要和这个二进制数进行按位或运算,其中需要变化的位是1,其他位是0;
- 如果需要从1变成0,只需要和这个二进制数进行按位与运算,其中需要变化的位是0,其他位是1;
大写转小写
在本题中,将二进制数的第5位从0变成1,那么只需要将该二进制数和二进制数0100000按位或即可:

而当该字母本身就是小写字母时,则二进制数不发生改变,即小写字母还是原来的小写字母
而二进制数00100000转换后得到十进制数32,因此如果需要将大写字母转换成小写字母,同时小写字母不变,只需要把这个字符按位或32即可:
1 | b := 'A' |
小写转大写
如果需要将小写转换成大写字母,需要将小写字母的二进制编码的第五位从1变成0,则需要将二进制数和二进制数11011111按位与即可。

而当该字母本身就是大写字母时,则二进制数不发生改变,即大写字母还是原来的大写字母
如何将110111111转换成十进制数呢?
二进制中最高位表示符号位,最高位是1时是负数,0是负数。
负数的计算方式:
1 | -64+16+8+4+2+1 = -33 |
如果需要将小写字母转换成大写字母,同时大写字母不变,只需要把这个字符按位与-33即可:
1 | b := 'A' |
大写转小写,小写转大写
也就是二进制的第5位1变为0,同时0变为1.
小写转大写:

大写转小写:

将00100000转换成十进制是32.
如果需要将小写字母转换成大写字母,同时大写字母转换成小写字母,只需要把这个字符按位异或32即可:
1 | b := 'A' |
总结
- 大写转小写、小写转大写:字符^=32;
- 大写转小写、小写转小写:字符|=32;
- 小写转大写、大写转小写:字符&=-33;
完。