Java:确定一个单词是否包含可以在另一个单词中找到的字母?

时间:2015-02-27 02:56:50

标签: java string contains

例如: 如果你有一个String" magikarp",并且你对" karma"进行了测试,这将是真的,因为所有组成的信件都是" karma"可以在" magikarp"。

中找到

" KIPP"将返回false,因为只有一个" p"在" magikarp。"

这是我现在的尝试,但我认为它非常有效,而且当一个字母多次出现时,它并没有正确返回。< / p>

private boolean containsHelper(String word, String word2){      
    for (int i = 0; i < word2.length(); i ++){
        if (!word.contains(String.valueOf(word2.charAt(i)))){
            return false;
        }
    }
    return true;
}

4 个答案:

答案 0 :(得分:2)

我不在这里写程序,但让你知道怎么做。考虑到复杂性,有两种方法可以做到这一点:

1)如果您确定在字符串中只获得a-z / A-Z字符,则取一个大小为26的数组。循环第一个字符串并将字符的计数出现在相应的索引中。比如说你有String“aabcc”。现在数组看起来像[2,1,2,0,... 0]。现在循环遍历第二个String,并在每个字符处,从相应字符位置的数组中减去1并检查结果值。如果value小于0,则返回false。例如,你有“aacd”。当你在d时,你会做(0-1),结果-1小于0,因此返回false。

2)对每个String中的字符进行排序,然后进行比较。

答案 1 :(得分:1)

您需要确保对于第二个字符串中显示的任何字符cc出现在第二个字符串中的次数不大于 c出现在第一个字符串中的次数。

解决此问题的一种有效方法是使用 hashmap 来存储第一个字符串的字符数,然后遍历第二个字符串中的字符以检查它们的总计数是否为不大于第一个字符串中的值。在最坏的情况下,时间和空间复杂度为O(n),其中n是输入字符串的长度。

以下是供您参考的示例代码:

import java.util.HashMap;
import java.util.Map;

public class HashExample {

    public static void main(String[] args) {
        System.out.println(containsHelper("magikarp", "karma"));     // true
        System.out.println(containsHelper("magikarp", "kipp"));      // false    
    }

    private static boolean containsHelper(String word, String word2) {

        Map<Character, Integer> hm = new HashMap<>();

        for (int i = 0; i < word.length(); i++) {
            Character key = word.charAt(i);
            int count = 0;

            if (hm.containsKey(key)) {
                count = hm.get(key);
            }    
            hm.put(key, ++count);
        }

        for (int i = 0; i < word2.length(); i++) {
            Character key = word2.charAt(i);

            if (hm.containsKey(key)) {
                int count = hm.get(key);

                if (count > 0) {
                    hm.put(key, --count);
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
        return true;
    }
}

答案 2 :(得分:1)

由于您只检查字符,因此使用indexOf并检查它是否返回-1会更有效contains本身调用indexOf但是还有其他一些修剪。 ..

但是,我认为将String转换为char数组并删除它们会更简单,如果找到它们也可以处理多次出现的情况。

所以你的算法看起来像这样:

private final boolean containsHelper(final String word, final String word2)
{
    char[] secondWordAsCharArray = word2.toCharArray();
    char[] firstWordAsCharArray = word.toCharArray();

    Arrays.sort(firstWordAsCharArray);//Make sure to sort so we can use binary search.

    int index = 0;
    for(int i = 0; i++ < secondWordAsCharArray.length;)
    {
        index = Arrays.binarySearch(firstWordAsCharArray, secondWordAsCharArray[i]);//Binary search is a very performant search algorithm

        if(index == -1)
            return false;
        else
            firstWordAsCharArray[index] = ''; //A SENTINEL value, set the char a value you are sure that will never be in word2.
    }
}

基本上,我所做的是:

  • 将两个单词转换为char数组以使其更容易。
  • 对我们检查的单词的char数组进行排序,以便我们可以使用二进制搜索。
  • 循环第二个单词的所有字符。
  • 使用二进制搜索算法检索索引(一个非常高效的char算法,据我所知最好)。
  • 如果index为-1,则找不到它,所以我们可以返回false。
  • 否则请确保我们取消该角色。

答案 3 :(得分:0)

可能的算法是删除第二个单词中不会出现在第一个单词中的所有字母,对它们进行排序然后进行比较。

这是在Java 8中实现这一目标的合理方法:

List<Integer> wordChars = word.chars().sorted().collect(Collectors.toList());
List<Integer> searchChars = search.chars()
    .filter(wordChars::contains).sorted().collect(Collectors.toList());
return wordChars.equals(searchChars);