2

到目前为止,我已经想出了这个。我试图最小化字符串操作并隔离内置数据类型、数组和整数操作的解决方案。

我正在寻找更优雅的方法来检查 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;
    }
4

5 回答 5

4

如果你想要一个难以理解的几行答案:

private static boolean isPangrams(String ip) {
  return 26== (new HashSet(Arrays.asList(ip.toUpperCase().replaceAll("[^A-Z]", "").toCharArray()))).size();
}

解释:

  1. 将字符串设为大写(将 'a' 和 'A' 处理为相同)
  2. 删除所有字符不是 A, B ... Z
  3. 将其转换为char[]
  4. 将数组转换为Collection
  5. 将集合添加到 aSet以摆脱所有双峰
  6. 测试集合的大小。

您应该意识到此代码不易阅读且性能不佳。

于 2016-06-17T11:36:20.857 回答
4

您可以为此使用按位运算:

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;
}

涂鸦

代码的工作方式如下:我们考虑一个 32 位数字的 int。最多 26 位的每一位都是一个标志(可以boolean这么说)。最初所有标志都是false因为我们flags0.

现在我们遍历字符串的字符。如果字符是小写字母,我们将对应标志的标志设置为true(不管true之前是否设置为)。

最后我们检查最低 26 位是否都设置为true. 如果是,flags则等于0x3ffffff(这是一个等于1111111111111111111111二进制的十六进制数。如果是,我们返回true。否则,我们返回false

通常按位运算比if语句和布尔运算要快,所以我希望这个程序会快很多。

于 2016-06-17T11:38:16.807 回答
2

如果字符串包含 int 变量中的给定字母,则可以“打包”数据。

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

于 2016-06-17T11:40:00.000 回答
0

如果你发现 map[122 - asciiCode] 不等于零,你可以用 return false 语句停止整个方法,因为从那以后它不再是 pangram 并且你放弃了 for() 的其余部分 - 我是对的吗?我知道这不是您所期望的改进(尤其是只有 26 个步骤),而只是我想到的

        if (map[122 - asciiCode] == 0) {

            sum += 1;
            map[122 - asciiCode] = 1;
        } else return false;
于 2016-06-17T11:31:59.340 回答
0

最有效的解决方案 O(n) 时间复杂度:

  1. 遍历字符串并将每个字母放入HashMap( key: letter, value: count)
  2. 遍历地图并检查字母表中的每个字母
于 2016-06-17T11:33:58.897 回答