如何使用anagrams彼此相邻的字符串数组进行排序

时间:2013-03-20 04:27:03

标签: algorithm sorting

如何使用彼此相邻的字谜对字符串数组进行排序?

例如:

输入{god,dog,abc,cab,man}
输出{abc,cab,dog,god,man}

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

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

我们能做得比这更好吗?

9 个答案:

答案 0 :(得分:12)

你当然可以做得更好,如下:

  1. 循环遍历字符串数组
  2. 对于每个字符串,首先使用已排序的字符串对其字符进行排序 作为键和原始字符串作为值,放入哈希表。你最终会得到一个哈希表 将键作为排序字符串,值为所有字谜,同时,这些值是有序的。您可以使用map<string, set<string> >为此目的服务。
  3. 遍历哈希表并将所有字谜输出到一起 给定密钥,它们应该彼此相邻
  4. 假设字符串的长度为M,数组的大小为N. 那么时间复杂度为:O(NMlogM),M通常平均小于N.所以这比你说的要高效得多。

答案 1 :(得分:3)

#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是单词存在的最大字谜数

答案 2 :(得分:2)

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

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

其中键是按字母排序的字母顺序。对于字谜来说,关键是相同的,因此将它们保持在一起

答案 3 :(得分:1)

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

答案 4 :(得分:0)

为什么要排在第一位?不能只是根据字谜将数组划分为子集。对子集进行排序,最后根据每个子集中的第一个单词进行合并。

答案 5 :(得分:0)

把它放在一个真正的&#39; java编程上下文(即我们使用一些现有的和基本的jdk util类,我认为以下方法可能会为这个主题提供另一个有趣的方面(即&#34;如何使用anagrams彼此相邻排序字符串数组&#34; ):

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

下面是代码和结果(这个想法可以在第9章中看到,&#34;破解编码面试&#34;例如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);
    }


}

输入:{&#34; abets&#34;,&#34; mates&#34;,&#34; baste&#34;,&#34; meats&#34;,&#34; betas&#34; ,&#34; beast&#34;,&#34; steam&#34;,&#34; tames&#34;,&#34; beats&#34;,&#34; teams&#34;};

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

答案 6 :(得分:0)

从互联网上找到解决方案:

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 :(得分:0)

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 :(得分:0)

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