文章目录
题目链接
https://leetcode.cn/problems/to-lower-case/
题目
官方思路
方案一 Java API实现大小写转换
String类的常用方法包括:
String toLowerCase():使用默认语言环境,将String中所有字符转换为小写
String toUpperCase():使用默认语言环境,将String中所有字符转换为大写
class Solution {
public String toLowerCase(String s) {
return s.toLowerCase();
}
}
方案二 哈希表
使用一个哈希映射,哈希映射中包含26个键值对(A,a),(B,b),(C,c),…,(Z,z)。对于每一个待转换的字符ch,如果它出现在哈希映射中(即ch时哈希映射中的一个键),那么ch是大写字母,我们直接获取ch在哈希映射中的值即可得到对应的小写字母;如果它没有出现在哈希映射中,那么ch是其他字符,我们无需进行转换
然而,这种方法需要一定的辅助空间,不够简洁
方案三 位运算实现大写到小写转换(巧妙)
一种更好的方法就是观察小写字母和大写字母的ASCII表示:
- 大写字母 A - Z 的ASCII码范围为[65,90]
- 小写字母 a - z 的ASCII码范围是[97,122]
进而可以发现,对于[65,90]对应的二进制表示为[ 0100 0001 , 0101 1010 ],32对应的二进制表示为 0010 0000,对于[ 0100 0001 , 0101 1010 ]内的所有数,表示32的那个二进制位都是0,因此。可以对ch的ASCII码与32做按位或运算,代替与32的加法运算
class Solution {
public String toLowerCase(String s) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c >= 65 && c <= 90){
c |= 32;
}
builder.append(c);
}
return builder.toString();
}
}
扩展 - 位运算实现字母大小写转换
大写转小写
字符 与 32 按位或运算(上面已经解释)
小写转大写
字符与 -33 按位与运算
-33 的 二进制表示为 1101 1111
对于[97,122]对应的二进制表示为[ 0110 0001 , 0111 1010 ],32对应的二进制表示为 0010 0000,对于[ 0110 0001 , 0111 1010 ]内的所有数,表示32的那个二进制位都是1,因此。可以对ch的ASCII码与-33做按位与运算,代替与32的减法运算
借着上面那一题的测试程序测试一下:
class Solution {
public String toLowerCase(String s) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c >= 97 && c <= 122) {
c &= (-33);
}
builder.append(c);
}
return builder.toString();
}
}
输入:
"Hello"
"here"
"LOVELY"
输出:
"HELLO"
"HERE"
"LOVELY"
最终封装好的转换成大写字母的函数为:
public String toUpperCase(String s) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c >= 97 && c <= 122) {
c &= (-33);
}
builder.append(c);
}
return builder.toString();
}
大写变小写,小写变大写
字符 与 32 按位异或运算
通过上面的分析可以知道:
-
大写字母 A - Z 的ASCII码范围为[65,90]
- 对于[65,90]对应的二进制表示为[ 0100 0001 , 0101 1010 ],32对应的二进制表示为 0010 0000,对于[ 0100 0001 , 0101 1010 ]内的所有数,表示32的那个二进制位都是0
-
小写字母 a - z 的ASCII码范围是[97,122]
- 对于[97,122]对应的二进制表示为[ 0110 0001 , 0111 1010 ],32对应的二进制表示为 0010 0000,对于[ 0110 0001 , 0111 1010 ]内的所有数,表示32的那个二进制位都是1
所以,可以进行按位异或运算,异或运算的口诀是:相同为0,不同为1
如果是大写字母[65,90],表示32的二进制位是0,与32进行异或,0就会变成1,实现加32的操作,从而转换成小写字母
如果是小写字母[97,122],表示32的二进制位都是1,与32进行异或,1就会变成0,实现减32的操作,从而转换成大写字母
同样,借LeetCode的测试程序验证一下:
输入:
"Hello"
"here"
"LOVELY"
输出:
"hELLO"
"HERE"
"lovely"
最终封装好的字母大小写转换的函数为:
public String toChangeCase(String s) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if ((c >= 97 && c <= 122) || (c >= 65 && c <= 90)) {
c ^= 32;
}
builder.append(c);
}
return builder.toString();
}