由于您要对单词进行排序,我假设所有字符的 ascii 值都在 0-255 范围内。然后你可以对这些词做一个Counting Sort。
计数排序将花费与输入单词大小相同的时间。从计数排序获得的字符串的重建将花费 O(wordlen)。您不能使此步骤小于 O(wordLen),因为您必须至少迭代字符串一次,即 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]}