我有多个订单,每个订单都包含已购买的Item
个对象。
1 : {Item1, Item2, Item3, Item4, Item5}
2 : {Item2, Item8, Item4, Item3, Item11, Item5}
3 : { ... }
我的目标是确定每个项目的购买频率,并能够在O(1)中获得结果。
我的想法是迭代订单,基于子集项 - 增加特定数组的元素。这将为我提供在O(1)中提取所需值的可能性。
EG。 Item3和Item4被买了2次。
int frequency = myArray[getHash(Item3+Item4)]
print frequency;
Output : 2
问题:
开发一个int getHash(...)
函数,它可以对项目的子集进行哈希处理。
注意:{Item1,Item2} = {Item2,Item1}
非常感谢!欢迎任何更好的想法的帮助!
答案 0 :(得分:4)
因为{A,B} = {B,A}
您首先需要在继续之前对列表进行排序。您排序的并不重要,但您确实需要确保没有任何值被视为排序目的,除非它们在排序中可以互换。
接下来,任何简单的哈希算法都应该有效。一种常见的技巧是使用两个素数,我称之为c
和p
。
int hash = c;
foreach(Item i in items) hash = hash * p + i.GetHashCode()
return hash;
p
有时被选为31,因为它不仅是素数,而且编译器将其解析为比特移位和减法,这比乘法快得多。 x * 31
与(x << 5) - 1
相同(假设我使用了正确的班次......我不时搞砸了,哈哈。)
答案 1 :(得分:0)
对不起,我没有使用哈希,但是我试着以一种我想做的方式试一试。就像试图解决这种挑战一样。
Dictionary<Item, Dictionary<Item, Count>> combine = new Dictionary<Item, Dictionary<Item, Count>>();
foreach (Item item in Sell)
{
Dictionary<Item, int> key;
if (!combine.TryGetValue(item, out key))
{
key = new Dictionary<Item, Count>();
combine.Add(item, key);
}
foreach (Item otherItem in Sell)
{
if (item == otherItem)
continue;
Count count;
if (key.TryGetValue(otherItem, out count))
count++;
else
key.Add(otherItem, new Count());
}
}
这可能是非常愚蠢的,因为对于每个项目,你最后都会得到一个同时用柜台购买的所有其他物品的字典。如果你想知道Item1是否与Item2 AND Item3和Item2 OR Item3 ...... Bleh同时购买。没关系。