如何解决排序的字谜

时间:2017-05-05 15:43:28

标签: java algorithm data-structures collections

我有一个单词列表如下。

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]

有人可以告诉我这里有什么问题吗?

3 个答案:

答案 0 :(得分:0)

这将解决您的问题

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&lt; String,ArrayList&lt;串GT;&GT;像这样的数据结构。希望这会有所帮助:)

答案 1 :(得分:0)

我会这样做:

  • 对于每个单词,创建一个Map<Character, Integer>,其中包含单词的字符(不包括空格)和出现次数 - 您已经做过类似的事情
  • 然后将它们存储在Map<Map<Character, Integer>, List<String>>中,其中键是出现的地图,值是所有匹配的单词列表(anagrams)。 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);

答案 2 :(得分:0)

您在代码中犯了一些错误。首先,您需要更改在集合中存储字谜的逻辑。你在这里存储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向前移动,因此如果下一个元素为{ {1}}然后当你递增anagram时,你会错过它。最后一个错误是您需要检查j列表的所有元素。因为最后一个元素可能不是带有任何其他元素的anagram,所以需要单独进行。

因此,在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();
        }

    }
}