【问题标题】:How to solve for sorted anagrams如何解决排序的字谜
【发布时间】:2017-05-05 15:43:28
【问题描述】:

我有一个单词列表如下。

pear amleth dormitory tinsel dirty room hamlet listen silnet

我想找出所有字谜并按排序顺序列出它们。如果什么也没找到,就输出那个词。所以在上述情况下,输出应该是。

amleth,hamlet dirty room,dormitory listen,silnet,tinsel pear

下面是我为此编写的 java 代码。

public class Anagram {

    private  boolean isAnagram(String s1, String s2) {

        if (s1.length() != s2.length()) {
            return false;
        }
        Map<Character, Integer> anagramMap = new HashMap<>();
        for (char ch = 'a'; ch <= 'z'; ++ch) 
             anagramMap.put(ch, 0); 
        for(int i=0; i<s1.length(); i++){
            anagramMap.put(s1.charAt(i), anagramMap.get(s1.charAt(i))+1);
        }
        for(int j=0; j<s2.length(); j++) {
            if (anagramMap.get(s2.charAt(j)) != 0) {
                anagramMap.put(s2.charAt(j), anagramMap.get(s2.charAt(j)) - 1);
            }
        }
        for(int value : anagramMap.values()) {
            if (value != 0) {
                return false;
            }
        }
        return true;
    }
    private void solveChallenge(List<String> words) {
        for(int i=0 ;i<(words.size()-1); i++) {
            Set<String> result = new TreeSet<>();
            for(int j=(i+1); j< words.size(); j++) {
                if (isAnagram(words.get(i), words.get(j))){
                    result.add(words.get(i) + " " + words.get(j));
                    System.out.println(result);
                    words.remove(j);
                }
            }
        }
    }

    public static void main(String[] args) {
        Anagram anagram = new Anagram();
        List<String> words = new ArrayList<>();
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        try {
            String line = reader.readLine();
            Integer numTestCases = Integer.parseInt(line);
            while (--numTestCases >= 0){
                words.add(reader.readLine().replaceAll("\\s+","").toLowerCase());
            }
            System.out.println(words);
            new Anagram().solveChallenge(words);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

但它没有列出所需的输出。我得到的输出是 [amleth hamlet] [dormitory dirtyroom] [tinsel lisetn]

谁能告诉我这里出了什么问题?

【问题讨论】:

  • 但它没有列出所需的输出。你能显示你得到的输出吗?
  • 我不明白你怎么能期望你的程序产生你描述的输出。它成对地比较和输出结果,但您希望容纳超过两个字谜的组。此外,您从输入的单词中去除空格;这些都丢失了——当你输出结果时你无法重现它们。此外,您根本没有任何机制来输出不是任何其他输入的字谜的输入。 您需要一种完全不同的方法
  • 考虑在阅读输入时形成相互字谜组,并延迟输出直到阅读并分组整个输入。
  • 虽然我确信您的 isAnagram 方法可以正常工作,但检查字谜的标准方法是对字母进行排序并比较排序顺序。由于 amleth 和 hamlet 都产生 aehlmt,因此它们是字谜。另一个优点是您可以使用 `Map> 来保存字谜,因此所有的 listen、silnet 和 tinsel 都将存储在 eilnst 键下。
  • boolean isAnagram(String a, String b) { char[] ca = a.toCharArray(); char[] cb = b.toCharArray(); Arrays.sort(ca); Arrays.sort(cb); return Arrays.equals(ca,cb);}

标签: java algorithm data-structures collections


【解决方案1】:

您在代码中犯了一些错误。首先,您需要更改在集合中存储字谜的逻辑。您将pair 存储在集合中,而不是您应该将所有字谜存储在这里。所以你可以有一个StringBuilderanagrams 存储在一个single 传递中,并且在迭代之后,你可以将它添加到集合中。

另一个错误是在这个循环中:

for(int j=(i+1); j< words.size(); j++) {
    if (isAnagram(words.get(i), words.get(j))){
        result.add(words.get(i) + " " + words.get(j));
        System.out.println(result);
        words.remove(j);
    }
}

在这里,您要从列表中删除 element,然后递增 j 因此,删除后,所有元素可能会向前移动 1 位置,因此如果下一个元素是 anagram,那么您将错过当您增加j 时,它会增加。最后一个错误是您需要检查words 列表的所有元素。因为最后一个元素有可能与其他元素没有字谜,所以需要单独取。

所以对solveChallenge()函数做一些改动:

private void solveChallenge(List<String> words) {
    for(int i=0 ;i<(words.size()); i++) {
        Set<String> result = new TreeSet<>();
        StringBuilder resultant_string = new StringBuilder(words.get(i)); //To store the all anagrams
        for(int j=(i+1); j< words.size(); j++) {
            if (isAnagram(words.get(i), words.get(j))){
                resultant_string.append(" ").append(words.get(j));
                words.remove(j);
                j--;       //If anagram found, stay on the current element
            }
        }
        result.add(resultant_string.toString());
        System.out.println(resultant_string);
    }
}

根据您的需要,我对程序进行了一些更改。

代码:

class Anagram {

    private  boolean isAnagram(String s1, String s2) {
        s1=s1.replaceAll("\\s+","");
        s2=s2.replaceAll("\\s+","");
        if (s1.length() != s2.length()) {
            return false;
        }
        Map<Character, Integer> anagramMap = new HashMap<>();
        for (char ch = 'a'; ch <= 'z'; ++ch) 
             anagramMap.put(ch, 0); 
        for(int i=0; i<s1.length(); i++){
            anagramMap.put(s1.charAt(i), anagramMap.get(s1.charAt(i))+1);
        }
        for(int j=0; j<s2.length(); j++) {
            if (anagramMap.get(s2.charAt(j)) != 0) {
                anagramMap.put(s2.charAt(j), anagramMap.get(s2.charAt(j)) - 1);
            }
        }
        for(int value : anagramMap.values()) {
            if (value != 0) {
                return false;
            }
        }
        return true;
    }
    private void solveChallenge(List<String> words) {
        List<String> result = new ArrayList<>();
        for(int i=0 ;i<(words.size()); i++) {
            List<String> resultant_strings=new ArrayList<> ();
            resultant_strings.add(words.get(i));

            for(int j=(i+1); j< words.size(); j++) {
                if (isAnagram(words.get(i), words.get(j))){
                    resultant_strings.add(words.get(j));
                    words.remove(j);
                    j--;
                }
            }
            Collections.sort(resultant_strings);
            String resultant_string=resultant_strings.toString();
            result.add(resultant_string);
        }
        Collections.sort(result);
        System.out.println(result);
    }

    public static void main(String[] args) {
        Anagram anagram = new Anagram();
        List<String> words = new ArrayList<>();
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        try {
            String line = reader.readLine();
            Integer numTestCases = Integer.parseInt(line);
            while (--numTestCases >= 0){
                words.add(reader.readLine().toLowerCase());
            }
            System.out.println(words);
            new Anagram().solveChallenge(words);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

打印结果:

[[amleth, hamlet], [dirty room, dormitory], [listen, silnet, tinsel], [pear]]

【讨论】:

  • 这适用于大多数部分,但在输出中省略了“脏房间”中的空间。还需要对整个输出进行排序,即梨应该排在最后。
【解决方案2】:

这会解决你的问题

public class Anagram {

private  boolean isAnagram(String s1, String s2) {

    if (s1.length() != s2.length()) {
        return false;
    }
    Map<Character, Integer> anagramMap = new HashMap<>();
    for (char ch = 'a'; ch <= 'z'; ++ch) 
         anagramMap.put(ch, 0); 
    for(int i=0; i<s1.length(); i++){
        anagramMap.put(s1.charAt(i), anagramMap.get(s1.charAt(i))+1);
    }
    for(int j=0; j<s2.length(); j++) {
        if (anagramMap.get(s2.charAt(j)) != 0) {
            anagramMap.put(s2.charAt(j), anagramMap.get(s2.charAt(j)) - 1);
        }
    }
    for(int value : anagramMap.values()) {
        if (value != 0) {
            return false;
        }
    }
    return true;
}
private void solveChallenge(List<String> words) {
    for(int i=0 ;i<(words.size()-1); i++) {
        Set<String> result = new TreeSet<>();
        int j = i+1;
        while(j < words.size()) {
            if (isAnagram(words.get(i), words.get(j))){
                result.add(words.get(i) + " " + words.get(j));
                System.out.println(result);
                words.remove(j);
            } else {
             j++;
           }
        }
    }
}

public static void main(String[] args) {
    Anagram anagram = new Anagram();
    List<String> words = new ArrayList<>();
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    try {
        String line = reader.readLine();
        Integer numTestCases = Integer.parseInt(line);
        while (--numTestCases >= 0){
            words.add(reader.readLine().replaceAll("\\s+","").toLowerCase());
        }
        System.out.println(words);
        new Anagram().solveChallenge(words);
    } catch (IOException e) {
        e.printStackTrace();
    }

}
}

只有在不删除任何元素时才应该增加 j,因为 remove() 方法会导致问题。

现在我建议你应该使用 HashMap> 这样的数据结构。希望这会有所帮助:)

【讨论】:

    【解决方案3】:

    我会这样做:

    • 为每个单词创建一个Map&lt;Character, Integer&gt;,其中包含单词的字符(不包括空格)和出现次数 - 您已经完成了类似的操作
    • 然后将它们存储在Map&lt;Map&lt;Character, Integer&gt;, List&lt;String&gt;&gt; 中,其中键是出现映射,值是所有匹配单词的列表(字谜)。 Map::equals 会自动为您进行比较。

    示例实现可能如下所示:

    String[] words = ("pear", "amleth", ... }'
    Map<Map<Integer, Long>, List<String>> characters = new HashMap<> ();
    for (String word : words) {
      //here I'm using a stream, but you can build the occurences map manually
      Map<Integer, Long> occurences = word.replaceAll("\\s+", "") //remove spaces
                       .chars().boxed()
                       .collect(Collectors.groupingBy(i -> i, Collectors.counting()));
    
      if (characters.containsKey(occurences)) { //anagram found !
        characters.get(occurences).add(word); //add the word to the list
      } else { //no anagram found, create the list, with only one item
        List<String> list = new ArrayList<> ();
        list.add(word);
        characters.put(occurences, list);
      }
    }
    
    //you may want to sort the lists here
    
    characters.values().forEach(System.out::println);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-14
      • 1970-01-01
      • 2013-11-29
      • 2022-11-01
      • 2010-11-14
      • 2016-11-08
      • 1970-01-01
      • 2020-08-29
      相关资源
      最近更新 更多