Algorithm 在给定时间范围内查找多集的模式(最大多重性)

Algorithm 在给定时间范围内查找多集的模式(最大多重性),algorithm,time,multiset,Algorithm,Time,Multiset,给定的问题: 多集是其中某些元素出现一次以上的集合(例如,{A,f,b,b,e,c,b,g,A,i,b}是多集)。这些元素是从一个完全有序的集合中提取的。呈现一个算法,当以多集作为输入呈现时,查找多集中出现次数最多的元素(例如在{a,f,b,b,e,c,b,g,a,c,b},b中出现次数最多)。算法 应在O(n lg n/M+n)时间内运行,其中n是多集合中的元素数,M是多集合中元素的最高出现次数。请注意,您不知道M的值 [提示:使用基于列表中位数的分而治之策略。分而治之策略生成的子问题不能按顺

给定的问题:

多集是其中某些元素出现一次以上的集合(例如,{A,f,b,b,e,c,b,g,A,i,b}是多集)。这些元素是从一个完全有序的集合中提取的。呈现一个算法,当以多集作为输入呈现时,查找多集中出现次数最多的元素(例如在{a,f,b,b,e,c,b,g,a,c,b},b中出现次数最多)。算法 应在O(n lg n/M+n)时间内运行,其中n是多集合中的元素数,M是多集合中元素的最高出现次数。请注意,您不知道M的值

[提示:使用基于列表中位数的分而治之策略。分而治之策略生成的子问题不能按顺序小于“特定”大小 实现给定的时限。]

我们最初的解决方案是:

我们的想法是使用摩尔多数算法来确定多集是否包含多数候选集(例如,{a,b,b}具有多数,b)。在确定这是真是假之后,我们要么输出结果,要么使用给定的算法(称为Select)找到列表的中位数,并将列表拆分为三个子列表(小于或等于中位数的元素,以及大于中位数的元素)。同样,我们将检查每个列表,以确定是否存在多数元素,如果存在,这就是您的结果

例如,给定多集{a,b,c,d,d,e,f}

第一步:检查多数票。未找到,请根据中位数拆分列表

第二步:L1={a,b,c,d,d},L2={e,f}找到每一个的多数。未找到,请再次拆分列表

步骤3:L11={a,b,c}L12={d,d}L21={e}L22={f}检查每个元素的多数元素。L12返回d。在这种情况下,d是原始多重集合中出现最多的元素,因此是答案


我们面临的问题是,这种类型的算法是否足够快,以及是否可以递归完成,或者是否需要终止循环。正如提示所说,子问题不能小于“某个”大小,我们认为它是M(发生次数最多)

如果您想在现实生活中这样做,那么值得考虑使用哈希表来跟踪计数。每个哈希表访问的复杂度可以分摊为O(1),因此下面Python代码的总体复杂度为O(n)


如果你像在你的文章中描述的那样以最直接的方式使用递归,它将不会有期望的时间复杂度。为什么?让我们假设答案元素是最大的。然后它总是位于递归的右分支。但是我们首先调用左分支,如果所有元素在那里都是不同的,那么左分支可以更深入(得到大小为
1
的片段,而我们不想让它们小于
M

下面是一个正确的解决方案:


让我们按照问题中的描述,在每一步将数组分成三部分。现在让我们暂时离开,看看我们有什么:递归调用形成一棵树。为了获得所需的时间复杂度,我们永远不应该深入到答案所在的层次。为了实现这一点,我们可以使用带队列的广度优先搜索而不是深度优先搜索来遍历树。就这样

你能详述你的解决方案吗?因为我们不知道M的值(发生次数最多),我们如何继续沿着树往下走,直到找到答案?例如,使用输入{abcdef}。那么对于这个集合,我们还是先考虑摩尔多数算法吗?如果集合中没有多数元素,则根据中位数将列表分为三个列表,低、中、高?@MichaelSalvador Yes。但是,如果左半部分不包含多数元素,我们将首先处理中半部分和上半部分,而不是将其拆分。只有在它之后,我们才能进入下一层。我想我会跟随,但我很好奇,如果我们有这样一个列表,会发生什么。中位数将被计算为“d”,这将导致在树的下一级生成三个列表{abc}{dd}和{eee}。现在多数算法将返回中位数列表的d,尽管d不是我们的正确答案。一旦检查了列表的该部分,也将返回e。由于这两个元素,树将不会继续。在这一点上还有其他的比较吗?还是我做得不对?@MichaelSalvador我们需要继续探索其他部分,直到剩下的部分变得更小。所以最后一个应该被检查,然后在这个例子中结束了。但是,在“D”和“E”都返回的情况下,我们必须考虑每个列表的长度吗?我们怎么知道答案是e而不是d?多数算法将同时返回这两个元素,因为在这种情况下,d和e都是每个子列表的多数元素。
import collections
C = collections.Counter(['a','f','b','b','e','c','b','g','a','i','b'])
most_common_element, highest_count = C.most_common(1)[0]