【问题标题】:How to sort an array of strings with anagrams next to each other如何对具有字谜的字符串数组进行排序
【发布时间】:2013-03-09 01:29:20
【问题描述】:

如何排序一个字符串数组,其中的字谜彼此相邻?

例如:

输入{神、狗、abc、出租车、人}
输出 {abc, cab, dog, god, man}

我的方法: 在 O(nlogn) 中对数组进行排序(不考虑字谜的情况)。下一个, 拿起第一个字符串并为字符串创建一个直方图,并将直方图与数组中剩余的字符串直方图进行比较,并将匹配的字符串放在数组的适当位置..重复直到达到数组大小..这个算法最糟糕O(n^3) 的情况(如果我们假设在最坏的情况下,每个字符串的大小也是 n)和直方图表示的额外空间

取自参考的直方图方法: finding if two words are anagrams of each other

我们能做得比这更好吗?

【问题讨论】:

    标签: algorithm sorting


    【解决方案1】:

    你当然可以做得更好:

    1. 遍历字符串数组
    2. 对于每个字符串,首先使用排序后的字符串对其字符进行排序 作为键和原始字符串作为值,放入哈希表。你最终会得到一个哈希表 键是排序的字符串,值都是字谜,同时,这些值是有序的。为此,您可以使用map<string, set<string> > 服务。
    3. 遍历哈希表并将所有字谜一起输出 给定键,它们应该彼此相邻

    假设字符串的长度为 M,数组的大小为 N 那么时间复杂度为:O(NMlogM),M 通常平均小于 N。所以这比你说的要有效得多。

    【讨论】:

    • 我认为通过计算每个字符的数量来压缩单词足以计算地图的键。
    • @liuml07 你能详细说明一下吗?
    • @Hengameh 让我们举个例子:aabbcc,你将有 a2b2c2 作为键(在这种情况下,abcabc 也有 a2b2c2,所以它们是彼此的字谜)。
    • @taocp,请插入map cost logN,所以正确的时间复杂度是O( N (MlogM + logN) ),map不完全是哈希表,它是用二叉树实现的。您的解决方案不完整,因为在第 3 步遍历地图,将不能保证没有字谜的单词按递增顺序排列。请记住,地图的键是排序后的单词而不是原始单词
    【解决方案2】:
    #include <vector>
    #include <unordered_map>
    #include <string>
    #include <set>
    #include <algorithm>
    #include <iostream>
    
    using namespace std;
    
    vector<string> sort_string_anagram(vector<string> array)
    {
        unordered_map<string, set<string>> anagram;
    
        for(string word : array)
        {
          string sorted_word(word);
    
          sort(sorted_word.begin(),sorted_word.end());
    
          anagram[sorted_word].insert(word);
        }
    
        sort(array.begin(), array.end());
    
        vector<string> result;
    
        for(string word : array)
        {
            unordered_map<string,set<string>>::iterator iter;
    
            string sorted_word(word);
    
            sort(sorted_word.begin(), sorted_word.end());
    
            if( (iter = anagram.find(sorted_word)) != anagram.end() )
            {
               for(set<string>::iterator it = (iter->second).begin(); it!= (iter->second).end();++it)
               {
                  result.push_back(*it);
               }
               anagram.erase(iter);
            }
        }
        return result;
    }
    

    @Jitendard,@taocp,一个具有时间复杂度的完整解决方案:O( N(MlogM) + NlogN + N(MlogM + A) )。 N是数组大小,M是单词大小,A是单词存在的最大字谜数

    【讨论】:

      【解决方案3】:

      在 python 中,这可以通过以下方式完成:

      sorted(word_list, key=lambda word: ''.join(sorted(word.replace(" ", "").lower())))
      

      其中键是按字母顺序排序的字符。字谜的关键是相同的,从而将它们保持在一起

      【讨论】:

        【解决方案4】:

        @Song Wang : 甚至我也想过那样做。但是,一旦将字符串从 hashmap 中取出,您怎么知道放置字符串的顺序? 假设你提取
        K1 = "abc", V1 = "驾驶室"
        K2 = "abc", V2 = "abc"
        您怎么知道将哪个放在列表 1 或 2 中的第一位?
        也许你会再次对它们进行排序。但是,那将不利于复杂性。

        【讨论】:

        • 我应该说清楚,对于hashmap,我并不是说它是JAVA中使用的hashmap,因为hashmap没有顺序。这里需要一种有顺序的映射。您可以在 C++ 中使用 map> 来实现哈希表的目的。
        • 该问题不要求对字谜进行排序。要求将它们放在一起。所以,没有必要对它们进行排序。我说的对吗?
        • 但是如果我们真的希望它们按顺序排列,我们不能在@taocp 的解决方案中使用“TreeMap”,而不是“HashMap”吗? (很明显,我说的是Java)
        【解决方案5】:

        为什么首先排序?您不能仅根据字谜将数组划分为子集。对子集进行排序,最后根据每个子集中的第一个词进行合并。

        【讨论】:

          【解决方案6】:

          从网上找到解决办法:

          public static void sortStringWithAnagrams(String[] stringArray) {
              Arrays.sort(stringArray, new AnagramComparator());
          }
          
          public static class AnagramComparator implements Comparator<String> {
          
              public String getSortedString(String s) {
                  char[] content = s.toCharArray();
                  Arrays.sort(content);
                  return new String(content);
              }
          
              public int compare(String s1, String s2) {
                  return getSortedString(s1).compareTo(getSortedString(s2));
              }
          
          }
          

          【讨论】:

            【解决方案7】:
            import java.util.Arrays;
            import java.util.Comparator;
            
            /**
             * Sort an array of strings so that all anagrams are next to each other
             * @author asharda
             *
             */
            public class Anagram implements Comparator<String> {
            
            
              public static String  anagram(String input)
              {
                char []s=input.toCharArray();
                Arrays.sort(s);
                return new String(s);
              }
              public static void main(String[] args) {
                // TODO Auto-generated method stub
            
                String arr[]= {"abc","god","cab","dog"};
                Arrays.sort(arr, new Anagram());
                for(String s:arr)
                System.out.println(s);
            
              }
              @Override
              public int compare(String arg0, String arg1) {
                return arg0.compareTo(arg1);
              }
            
            
            }
            
            //Credit to Cracking Coding Interview by Gayle Laakmann
            

            【讨论】:

              【解决方案8】:

              把它放在一个“真正的”java 编程上下文中(即我们使用一些现有的和基本的 jdk util 类,我认为以下方法可能会给这个主题带来另一个有趣的方面(即“如何使用 anagrams 对字符串数组进行排序彼此相邻”):

              (a) 我们定义一个比较器来判断两个字符串是否是字谜; (b) 我们使用 Arrays.sort(array,comparator) 对数组进行排序;

              下面是代码和结果(这个想法可以在第 9 章看到,例如 Gayle Laakmann 的“破解编码面试”)

              import java.util.Arrays;
              import java.util.Comparator;
              
              public class SolutionForSortArraysByAnagrams {
              
                  public static void main(String[] args){
              
                      String[] strArray = new String[]{"abets","mates","baste","meats", "betas","beast", "steam", "tames", "beats", "teams"}; 
              
                      sortArraysByAnagrams(strArray);
              
                      for(String str : strArray){
                          System.out.println(str);
                      }
              
                  }
              
                  private static void sortArraysByAnagrams(String[] strArray) {
              
                      Arrays.sort(strArray, new AnagramComparator());
              
                  }
              
              }
              
              
              class AnagramComparator implements Comparator<String> {
              
                  @Override
                  public int compare(String s1, String s2) {
              
                      //check edge conditions and length
                      if( s1 == null || s2 == null)
                          return -1;
                      if( s1.length() <  s2.length())
                          return -1;
                      else if ( s1.length() >  s2.length())
                          return 1;
              
                      //sort s1 and s2 to compare:
                      //System.out.println(s1 + " vs  " + s2);        
                      return sort(s1).compareTo(sort(s2));
              
                  }
              
                  private String sort(String s1) {
                      char[] cArray = s1.toCharArray();
                      Arrays.sort(cArray);        
                      //System.out.println(" sorted:  " + new String(cArray));
                      return new String(cArray);
                  }
              
              
              }
              

              输入:{“abets”、“mates”、“baste”、“meats”、“betas”、“beast”、“steam”、“tames”、“beats”、“teams”};

              输出: 教唆 绷 贝塔 兽 节拍 伙伴 肉类 蒸汽 驯服 团队

              【讨论】:

                【解决方案9】:
                 private static String[] getSortedAnagram(String[] array) {
                    Map<String, ArrayList<String>> sortedMap = new HashMap<>();
                    for (String a : array) {
                        String sortedString = a.chars().sorted().
                                collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();
                        sortedMap.computeIfAbsent(sortedString, s->new ArrayList<>()).add(a);
                    }
                   String[] output = new String[array.length];
                   List<String> list = sortedMap.values().stream().flatMap(List::stream).collect(Collectors.toList());
                   return list.toArray(output);
                }
                

                【讨论】:

                  猜你喜欢
                  • 2021-12-30
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-03-04
                  • 1970-01-01
                  • 2016-07-18
                  相关资源
                  最近更新 更多