単語を並べ替えるので、すべての文字の ascii 値が 0 ~ 255 の範囲にあると想定します。次に、単語に対してCounting Sortを実行できます。
カウントソートには、入力ワードのサイズと同じ時間がかかります。ソートをカウントして得られた文字列の再構築には、O(wordlen) がかかります。このステップを O(wordLen) 未満にすることはできません。文字列を少なくとも 1 回繰り返す必要があるためです。つまり、O(wordLen) です。事前定義された順序はありません。その単語のすべての文字を反復せずに、その単語について何らかの仮定を立てることはできません。従来の並べ替えの実装 (つまり、比較ベースのもの) では、O(n * lg n) が得られます。しかし、非比較のものは O(n) を与えます。
リストのすべての単語を繰り返し処理し、カウント ソートを使用して並べ替えます。並べ替えられた単語のマップを、それらがマップする既知の単語のリストに保持します。リストへの要素の追加には一定の時間がかかります。したがって、全体的なアルゴリズムの複雑さは O(n * avgWordLength) です。
これがサンプル実装です
import java.util.ArrayList;
public class ClusterGen {
static String sortWord(String w) {
int freq[] = new int[256];
for (char c : w.toCharArray()) {
freq[c]++;
}
StringBuilder sortedWord = new StringBuilder();
//It is at most O(n)
for (int i = 0; i < freq.length; ++i) {
for (int j = 0; j < freq[i]; ++j) {
sortedWord.append((char)i);
}
}
return sortedWord.toString();
}
static Map<String, List<String>> cluster(List<String> words) {
Map<String, List<String>> allClusters = new HashMap<String, List<String>>();
for (String word : words) {
String sortedWord = sortWord(word);
List<String> cluster = allClusters.get(sortedWord);
if (cluster == null) {
cluster = new ArrayList<String>();
}
cluster.add(word);
allClusters.put(sortedWord, cluster);
}
return allClusters;
}
public static void main(String[] args) {
System.out.println(cluster(Arrays.asList("tea", "eat", "abba", "aabb", "hello")));
System.out.println(cluster(Arrays.asList("moon", "bat", "meal", "tab", "male")));
}
}
戻り値
{aabb=[abba, aabb], ehllo=[hello], aet=[tea, eat]}
{abt=[bat, tab], aelm=[meal, male], mnoo=[moon]}