高效的Java语言构造来检查字符串是否是pangram?

时间:2016-06-17 11:20:40

标签: java algorithm performance optimization 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;
    }

5 个答案:

答案 0 :(得分: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. 的字符
  4. 将其转换为char[]
  5. 将数组转换为Collection
  6. 将该集合添加到Set以删除所有双重
  7. 测试集合的大小。
  8. 您应该意识到此代码不易阅读且不具备效果。

答案 1 :(得分:2)

您可以使用按位操作:

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

jDoodle

代码的工作原理如下:我们考虑一个32位数的int。每个最多26位是一个标志(可以说是boolean)。最初所有标记都是false,因为我们使用flags初始化0

现在我们迭代字符串的字符。如果字符是小写字母,我们将相应标志的标志设置为true(无论之前是否已设置为true)。

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

通常按位运算比if语句和布尔值更快,所以我希望这个程序更快一点。

答案 2 :(得分: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

答案 3 :(得分:0)

如果找到,可以使用return false语句停止整个方法           map [122 - asciiCode]不等于零,因为从那以后它再也没有pangram而你剩下的for() - 我是对的吗? 我知道这不是你所期望的改进(特别是只有26步),但只是让我想到的东西

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

            sum += 1;
            map[122 - asciiCode] = 1;
        } else return false;

答案 4 :(得分:0)

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

  1. 遍历字符串并将每个字母放入HashMapkey: letter, value: count
  2. 浏览地图并检查字母表中的每个字母