我需要改进这个问题的工作解决方案:
系统从网络中的用户获取消息。 每次用户发布消息时,我们都会为该用户增加总计数器(totCounter)和用户的消息计数器(userMessagesCounter)。为此,我们有一个带有用户(键)和userMessagesCounter(值)的哈希映射。 因此,为了获得在网络中发送超过10%消息的用户,我们所做的就是遍历散列表,检查每个用户if(userMessagesCounter / totCounter)> 0.1,如果是这样,我们将用户密钥添加到ArrayList。最后我们返回此列表。 这需要O(n)因为我们遍历所有用户。
我需要改进这个系统,让它尽可能快地运行。 我想到的是这样一个事实:不能超过10个用户,负载超过10%(因此我们有超过100%)。 因此,我可以创建一个大小为10的数组,并在消息到达时更新它。问题是当一条新消息到来时,这个数组信息可能不再有效了,我需要为每个到达的消息重新检查所有数组元素。
有没有人知道如何使用我提出的想法在O(10)(实际上就像O(1))中解决这个问题?
非常感谢。
答案 0 :(得分:0)
您正在寻找频繁的挖掘算法,该算法会查找在集合中重复theta
(在您的情况下为theta=0.1
)的项目。
Karp-Papadimitriou-Shanker提出了一种在线性时间内使用1/theta
空间处理它的方法:A Simple Algorithm for Finding Frequent
Elements in Streams and Bags
1. PF = ∅
2. foreach element e∈S {
3. if PF.hasKey(e) { // increase counter
4. PF.value(e)++ // of existing elements
5. }
6. Else {
7. PF.insert(e,1) // insert new element
8. If |PF|== 1/θ { // but if PF is full
9. Foreach key ∈ PF {
10. PF.value(k)-- // decrease all counters
11. if PF.value(k) == 0 { // and remove
12. PF.remove(k) // elements at 0
13. } } } } }
14. Output PF
取自lecture notes in Tehcnion's big data course
的伪代码在这里,您的"流"是发送的消息,当您查找频繁消息的用户时 - 请检查PF
中的当前候选人,O(1)
为常量theta=0.1
。
此算法会产生1/theta
(在您的情况下为10)候选人,因为它经常"但它有误报 - 这意味着它可能指出某些内容为"可能频繁&#34 ;,虽然它不是 - 但这不应该对你来说很难,因为你可以简单地验证它,
答案 1 :(得分:0)
我想我在这里看到了近乎O(1)的解决方案:
维护一个包含用户列表及其消息计数的字典。
您有10%的用户列表。这些是字典记录的链接,而不是本地副本。
当您收到消息时,您会查找该用户并增加其消息计数。这是O(1),因为它是一本字典。如果计数小于10%,请退出。
如果此用户已在10%列表中,请退出。如果列表按用户排序,则为O(4),否则为O(10)。
将此用户添加到10%列表。
清除不再是10%用户的所有用户的列表。 O(10)处于最坏的状态。
请求列表时:
清除不再是10%用户的所有用户的列表。再次,O(10)处于最坏情况 - 这与上述程序相同。
返回列表的副本。