简体   繁体   English

如何解决排序的字谜

[英]How to solve for sorted anagrams

I have a list of words as follows. 我有一个单词表,如下。

pear amleth dormitory tinsel dirty room hamlet listen silnet

I want to find out all anagrams and list them in sorted order. 我想找出所有字谜并将它们按排序顺序列出。 If nothing is found just output that word. 如果未找到任何内容,则输出该单词。 So in the above case the output should be. 因此,在上述情况下,输出应为。

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

Below is the java code I have written for that. 以下是我为此编写的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();
        }

    }
}

But it's not listing the desired output. 但是它没有列出所需的输出。 The output I get is [amleth hamlet] [dormitory dirtyroom] [tinsel lisetn] 我得到的输出是[amleth hamlet] [dormitory dirtyroom] [tinsel lisetn]

Can someone tell me what is wrong here? 有人可以告诉我这里有什么问题吗?

This will solve your problem 这将解决您的问题

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

}
}

You should increment j only when you are not removing any element because that remove() method caused problems. 仅当不删除任何元素时才应增加j,因为那个remove()方法会引起问题。

Now I would recommend you should use HashMap< String, ArrayList< String>> something like this data structure. 现在,我建议您使用HashMap <String,ArrayList <String >>这样的数据结构。 Hope this helps :) 希望这可以帮助 :)

This is how I would go about it: 这就是我要做的:

  • for each word, create a Map<Character, Integer> that contains the characters of the word (excluding spaces) and the number of occurence - you have already done something similar 为每个单词创建一个Map<Character, Integer> ,其中包含单词的字符(不包括空格)和出现的次数-您已经做过类似的事情
  • then store them in a Map<Map<Character, Integer>, List<String>> , where the key is the map of occurences and the value is a list of all the words that match (anagrams). 然后将它们存储在Map<Map<Character, Integer>, List<String>> ,其中键是出现的映射,值是所有匹配的单词(字谜)的列表。 Map::equals will do the comparison automagically for you. Map::equals将自动为您进行比较。

A sample implementation could look like this: 示例实现如下所示:

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

You have made few mistakes in the code. 您在代码中犯了一些错误。 First of all you need to change the logic of storing the anagrams in the set. 首先,您需要更改将字谜存储在集合中的逻辑。 You are storing here pair in the set rather you should store all anagrams here. 您将这pair存储在这里,而不是应该将所有字谜存储在这里。 So you can have a StringBuilder to store the anagrams in a single pass and after the iteration, You can add it to the set. 因此,您可以拥有一个StringBuildersingle存储anagrams ,并且在迭代之后,可以将其添加到集合中。

Another mistake is in this loop: 另一个错误是在此循环中:

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

Here you are removing an element from the list and then incrementing j So it is possible that after removal, all elements gets shifted ahead by 1 place so If next element is anagram then you will miss it as you are incrementing j . 在这里,您要从列表中删除一个element ,然后将j递增。因此,在删除之后,所有元素都可能会向前移1位置,因此,如果下一个元素是anagram那么您将在递增j错过它。 And last mistake is that you need to check for all elements of words list. 最后一个错误是您需要检查words列表的所有元素。 Because it may possible that last element is not anagram with any other element, Then it is required to be taken separately. 因为最后一个元素可能没有与任何其他元素相交,所以要求将其分开对待。

So Make few changes in solveChallenge() function: 因此,对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);
    }
}

As per your need, I have made some changes in the program. 根据您的需要,我对该程序进行了一些更改。

Code: 码:

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

    }
}

Prints result: 打印结果:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM