【问题标题】:Java: How to check if chars are contained in a stringJava:如何检查字符是否包含在字符串中
【发布时间】:2017-05-26 08:57:10
【问题描述】:

晚上,

我正在尝试找到解决此问题的最佳解决方案:

输入:

String1 = "algrtvy";
String2 = "alg";
String3 = "gvy";
String4 = "mgr";
String5 = "aall";

str2, 3, 4, 5的chars是否包含在1中?

输出

true 
true 
false
false

所以,我不是在检查序列(子字符串),而是检查单个字符。

有什么建议吗? 我正在寻找计算时间的快速解决方案。

解决方案:

此解决方案是来自@davidxxx 答案的实施版本。

public boolean haveChars(String longerString, String shorterString) {
    String chars = longerString;
    for (char c : shorterString.toCharArray()){
        int index = chars.indexOf(c);
        if (index == -1) {
            return false;
        } else {
            chars = chars.substring(0,index) + chars.substring(index + 1);
        }      
    }
    return true;
}

【问题讨论】:

  • 我不认为它是重复的,因为 OP 不需要检查子字符串。 OP 检查子序列。
  • 问题陈述具有误导性。 “包含在”表示子字符串,但 String3true 输出表明它与单个字符有关。
  • 它不是重复的@EnzoNocera,我不是在寻找子字符串,而是在寻找字符检查。
  • @jsheeran 确切地说,我不是在寻找子字符串

标签: java string character


【解决方案1】:

1) 将要在输入中查找的字符数存储在 int 值中。 它是可以知道匹配是否成功的计数器。

并复制当前模型以进行匹配。
这不是强制性的,因为String 是不可变的,但它使事情更清晰。

2) 迭代输入中包含的每个您尝试与模型副本匹配的字符。

3) 一旦字符匹配,递减计数器并将其从模型副本中删除。

4) 只要计数器的值为0,就意味着输入和模型匹配。

5) 如果输入的字符循环后,计数器的值不是0,说明输入和模型不匹配。

你可以有这样的方法:

public static boolean isMatch(String model, String input) {

    int nbCharacterRemaningToFind = input.length();
    String copyModel = model;

    for (char c : input.toCharArray()) {
        String cInString = String.valueOf(c);

        if (copyModel.contains(cInString)) {
            copyModel = copyModel.replaceFirst(cInString, "");
            nbCharacterRemaningToFind--;
            if (nbCharacterRemaningToFind == 0) {
                return true;
            }
        }

    }

    return false;
}

【讨论】:

  • 目前这是最好的解决方案,因为它考虑了双字符。但是是 O(n^2)... 而且我开始猜测不可能再低了。
  • 错误:空字符文字剩余字符 = remainingCharacters.replace(c, '');
  • 确实如此。我已经编写了代码而没有检查它的编译。对不起。 Character.MIN_VALUE 应该用于空字符。我已经编辑以提出一个更简单的解决方案。
  • 用您回答的解决方案编辑了问题。我只是做了一些更改以在中等情况下获得最佳计算时间。
【解决方案2】:

如果你的字符串很短,你可以使用

String string = "abcdefgh";
String sub = "adf";

boolean ok = sub.chars().allMatch(c -> string.indexOf((char) c) >= 0);

如果 M 是 string 的大小,N 是 sub 的大小,最坏的情况是 O(N * M)。

如果它很大,或者如果你想对同一个字符串进行多次检查,你可以先将它设为一个 Set,并使用相同的原则:

Set<Character> set = string.chars().mapToObj(c -> ((char) c)).collect(Collectors.toSet());
ok = sub.chars().allMatch(c -> set.contains((char) c));

这是 O(M) + O(N)。

另一种可能性是从子字符串中创建一个集合:

Set<Character> subset = sub.chars().mapToObj(c -> ((char) c)).collect(Collectors.toSet());
for (int i = 0; i < string.length() && !subset.isEmpty(); i++) {
    subset.remove(string.charAt(i));
}
ok = subset.isEmpty();

再次 O(M) + O(N)。

您现在应该衡量您的预期输入。但请注意:Java 中的基准测试很难。

【讨论】:

  • 感谢您的回答,但我试图避免使用其他数据结构。
【解决方案3】:

请注意,这可能是一个低效的解决方案,但我在这里尝试使用 containsALL 检查集合的内容是否包含在另一个集合中

String string1 = "algrtvy";

    //turn it to arraylist
    List<String> string1ArrayList = Arrays.asList(string1.split(""));
    String string2 = "alg";
    String string3 = "gvy";
    String string4 = "mgr";
    String string5 = "aall";

    //check its in the arraylist
    System.out.println(string1ArrayList.containsAll(Arrays.asList(string2.split(""))));
    System.out.println(string1ArrayList.containsAll(Arrays.asList(string3.split(""))));
    System.out.println(string1ArrayList.containsAll(Arrays.asList(string4.split(""))));
    System.out.println(string1ArrayList.containsAll(Arrays.asList(string5.split(""))));

*

结果:真真假真

*

【讨论】:

  • 嗯,你的回答不正确,结果应该是:true true false false,但是谢谢!
  • 不允许重复,例如aa 应该只匹配一个 a?在“aall”的情况下
【解决方案4】:

您可以像这样简单地检查创建一个检查包含的新函数 (containsEachChar):`

public boolean containsEachChar(String string1, String string2) {
       for (char c : string2.toCharArray()) {
            if(string1.indexOf( c) == -1){
               return false;
            }
       }
       return true;
}
`    

语句 string1.indexOf(c) 返回 'c' 在 'string1' 中的位置。如果 'string1' 中不存在 'c',则返回 -1。

现在,你可以从你的 main 方法调用上面的方法:`

     public static void main(String[] args) {
        String string1 = "algrtvy";
        String string2 = "alg";
        String string3 = "gvy";
        String string4 = "mgr";
        System.out.println(containsEachChar(string1, string2));
        System.out.println(containsEachChar(string1, string3));
        System.out.println(containsEachChar(string1, string4));
    }

输出: 真的 真的 假的

containsEachChar 中的代码所做的是,

  1. 它迭代 string2 中的字符。
  2. 如果 string1.indexOf(c) 的值为 -1,则无需进一步检查 string2 中的字符,因此该函数仅返回 false。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-23
    • 1970-01-01
    • 2014-12-27
    • 1970-01-01
    • 1970-01-01
    • 2017-08-29
    • 2011-11-09
    • 2013-05-18
    相关资源
    最近更新 更多