【问题标题】:Java: Determining if a word contains letters that can be found in another word?Java:确定一个单词是否包含可以在另一个单词中找到的字母?
【发布时间】:2015-04-29 16:10:48
【问题描述】:

例如: 如果您有一个字符串“magikarp”,并且您针对“karma”进行了测试,这将是正确的,因为构成“karma”的所有字母都可以在“magikarp”中找到。

“kipp”会返回 false,因为“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;
}

【问题讨论】:

标签: java string contains


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    可能的算法是从第二个单词中删除第一个单词中没有出现的所有字母,对两者进行排序,然后进行比较。

    这是在 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);
    

    【讨论】:

      【解决方案3】:

      您需要确保对于出现在第二个字符串中的任何字符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;
          }
      }
      

      【讨论】:

        【解决方案4】:

        由于您只检查字符,因此使用 indexOf 并检查它是否返回 -1 会更有效

        但是,我认为将 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。
        • 否则,请确保我们取消设置字符。

        【讨论】:

        • 您需要对firstWordAsCharArray 进行排序才能对其使用二分搜索
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-03-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-21
        • 2011-11-08
        • 2013-02-04
        相关资源
        最近更新 更多