如何将单词“need”转换为字符串“d1e2n1”而不是使用字典作为键?为了构建此字符串,您可以使用二叉树。字符将用作键,字符数用作值。二叉树是按键自动排序的,字典不是这样。
您可以通过将其二进制表示与 XOR 操作相结合,从单个哈希值计算组合哈希值。使用 C#,您可以执行以下操作:
public override int GetHashCode()
{
// Combine hashcode of a and b
return a.GetHashCode() ^ b.GetHashCode();
}
在未排序的列表中查找条目是 O(n) 操作。如果使用二进制搜索,则在排序列表中查找条目是 O(log(n)) 操作。
在字典中的列表中查找单词是 O(1 + n) 操作,与 O(n) 操作相同,或者 O(1 + log(n)) 操作,与O(log(n)) 操作。
编辑:
这是一个可能的实现:
var anagrams = new Dictionary<string, List<string>>();
foreach (string word in words) {
string key = GetFrequency(word);
List<string> list;
if (anagrams.TryGetValue(key, out list)) {
list.Add(word);
} else {
list = new List<string> { word };
anagrams.Add(key, list);
}
}
它使用这种方法来获取密钥:
private string GetFrequency(string word)
{
var dict = new SortedDictionary<char, int>(); // Implemented as binary tree
foreach (char c in word.ToLower()) {
int count;
if (dict.TryGetValue(c, out count)) {
dict[c] += 1;
} else {
dict[c] = 1;
}
}
return dict.Aggregate(new StringBuilder(), (sb, item) => sb.Append(item.Key).Append(item.Value), sb => sb.ToString());
}
使用这个定义来描述......
var words = new List<string> { "need", "eden", "team", "meat", "meta", "Nat", "tan" };
这个测试...
foreach (var item in anagrams.OrderBy(x => x.Key)) {
Console.WriteLine();
Console.WriteLine(item.Key + ":");
foreach (string word in item.Value.OrderBy(w => w)) {
Console.WriteLine(" " + word);
}
}
...产生这个输出
a1e1m1t1:
meat
meta
team
a1n1t1:
Nat
tan
d1e2n1:
eden
need
编辑#2:
这是 Ben Voigt 建议的频率计算
private string GetFrequencyByBenVoigt(string word)
{
char[] chars = word.ToLower().ToCharArray();
Array.Sort(chars);
return new string(chars);
}
测试结果将是
aemt:
meat
meta
team
ant:
Nat
tan
deen:
eden
need