高效的 Java 语言构造来检查字符串是否为 pangram?
Efficient Java language constructs to check if string is pangram?
到目前为止,我已经想到了这个。我试图最小化字符串操作并将解决方案隔离到内置数据类型、数组和整数操作。
我正在 java 中寻找更优雅的方法来检查 pangram 字符串。
优雅,代码行数最少,也欢迎其他高效算法。
请提供没有 lambda 表达式的建议。
private static boolean isPangrams(String ip) {
char[] characterArray = ip.toLowerCase().toCharArray();
int map[] = new int[26];
int sum = 0;
for(char current : characterArray) {
int asciiCode = (int) current;
if (asciiCode >= 97 && asciiCode <= 122) {
if (map[122 - asciiCode] == 0) {
sum += 1;
map[122 - asciiCode] = 1;
}
}
}
return sum == 26;
}
如果您发现,您可以使用 return 错误语句停止整个方法
map[122 - asciiCode] 不等于零,因为从那以后它就不再是 pangram 了,你省去了 for() 的其余部分——我说得对吗?
我知道这不是您期望的改进(尤其是只有 26 个步骤),而是我想到的东西
if (map[122 - asciiCode] == 0) {
sum += 1;
map[122 - asciiCode] = 1;
} else return false;
最有效的解决方案O(n)时间复杂度:
- 遍历字符串并将每个字母放入
HashMap
(key: letter, value: count
)
- 遍历地图并检查字母表中的每个字母
如果你想要一个难以理解的几行回答:
private static boolean isPangrams(String ip) {
return 26== (new HashSet(Arrays.asList(ip.toUpperCase().replaceAll("[^A-Z]", "").toCharArray()))).size();
}
解释:
- 将字符串设为大写(以处理 'a' 和 'A' 相同)
- 删除除 A、B ... Z 之外的所有字符
- 将其转换为
char[]
- 将数组转换为
Collection
- 将集合添加到
Set
以摆脱所有双胞胎
- 测试集合的大小。
您应该意识到这段代码不易阅读且性能不佳。
您可以为此使用按位运算:
private static boolean isPangrams(String ip) {
int flags = 0;
for(char current : ip.toLowerCase().toCharArray()) {
if (current >= 'a' && current <= 'z') {
flags |= 0x01<<(current-'a');
}
}
return flags == 0x3ffffff;
}
代码的工作原理如下:我们考虑一个 int,它是一个 32 位数字。最多 26 位的每一位都是一个标志(可以这么说 boolean
)。最初所有标志都是 false
因为我们用 0
初始化 flags
。
现在我们遍历字符串的字符。如果字符是小写字母,我们将对应标志的flag设置为true
(不管之前是否设置为true
)
最后我们检查最低26位是否都设置为true
。如果是这样,flags
等于 0x3ffffff
(这是一个等于 1111111111111111111111
二进制的十六进制数。如果是这样,我们 return true
。否则我们 return false
.
通常按位运算比 if
语句和布尔值快,所以我希望这个程序会快很多。
如果字符串在 int 变量中包含给定字母,则可以 'pack' 数据。
static boolean pangram (String s) {
int check = 0;
String lowerCase = s.toLowerCase();
for (int i = 0; i < lowerCase.length(); i++) {
char ch = lowerCase.charAt(i);
if (ch >= 'a' && ch <= 'z') {
check |= (1 << s.charAt(i) - 'a');
}
}
return check == 67108863;
}
最后的幻数是0b00000011111111111111111111111111
到目前为止,我已经想到了这个。我试图最小化字符串操作并将解决方案隔离到内置数据类型、数组和整数操作。
我正在 java 中寻找更优雅的方法来检查 pangram 字符串。
优雅,代码行数最少,也欢迎其他高效算法。
请提供没有 lambda 表达式的建议。
private static boolean isPangrams(String ip) {
char[] characterArray = ip.toLowerCase().toCharArray();
int map[] = new int[26];
int sum = 0;
for(char current : characterArray) {
int asciiCode = (int) current;
if (asciiCode >= 97 && asciiCode <= 122) {
if (map[122 - asciiCode] == 0) {
sum += 1;
map[122 - asciiCode] = 1;
}
}
}
return sum == 26;
}
如果您发现,您可以使用 return 错误语句停止整个方法 map[122 - asciiCode] 不等于零,因为从那以后它就不再是 pangram 了,你省去了 for() 的其余部分——我说得对吗? 我知道这不是您期望的改进(尤其是只有 26 个步骤),而是我想到的东西
if (map[122 - asciiCode] == 0) {
sum += 1;
map[122 - asciiCode] = 1;
} else return false;
最有效的解决方案O(n)时间复杂度:
- 遍历字符串并将每个字母放入
HashMap
(key: letter, value: count
) - 遍历地图并检查字母表中的每个字母
如果你想要一个难以理解的几行回答:
private static boolean isPangrams(String ip) {
return 26== (new HashSet(Arrays.asList(ip.toUpperCase().replaceAll("[^A-Z]", "").toCharArray()))).size();
}
解释:
- 将字符串设为大写(以处理 'a' 和 'A' 相同)
- 删除除 A、B ... Z 之外的所有字符
- 将其转换为
char[]
- 将数组转换为
Collection
- 将集合添加到
Set
以摆脱所有双胞胎 - 测试集合的大小。
您应该意识到这段代码不易阅读且性能不佳。
您可以为此使用按位运算:
private static boolean isPangrams(String ip) {
int flags = 0;
for(char current : ip.toLowerCase().toCharArray()) {
if (current >= 'a' && current <= 'z') {
flags |= 0x01<<(current-'a');
}
}
return flags == 0x3ffffff;
}
代码的工作原理如下:我们考虑一个 int,它是一个 32 位数字。最多 26 位的每一位都是一个标志(可以这么说 boolean
)。最初所有标志都是 false
因为我们用 0
初始化 flags
。
现在我们遍历字符串的字符。如果字符是小写字母,我们将对应标志的flag设置为true
(不管之前是否设置为true
)
最后我们检查最低26位是否都设置为true
。如果是这样,flags
等于 0x3ffffff
(这是一个等于 1111111111111111111111
二进制的十六进制数。如果是这样,我们 return true
。否则我们 return false
.
通常按位运算比 if
语句和布尔值快,所以我希望这个程序会快很多。
如果字符串在 int 变量中包含给定字母,则可以 'pack' 数据。
static boolean pangram (String s) {
int check = 0;
String lowerCase = s.toLowerCase();
for (int i = 0; i < lowerCase.length(); i++) {
char ch = lowerCase.charAt(i);
if (ch >= 'a' && ch <= 'z') {
check |= (1 << s.charAt(i) - 'a');
}
}
return check == 67108863;
}
最后的幻数是0b00000011111111111111111111111111