正如在线性时间多数算法?的答案中所看到的,可以在线性时间和log(n)
空间中计算元素数组的大多数。
已经证明,每个看到这个算法的人都认为它是一种很酷的技术。但是这个想法是否推广到新算法呢?
似乎这个算法的隐藏力量在于保持一个起复杂作用的计数器 -- 例如“(目前大多数元素的计数) - (目前第二多数元素的计数)”。是否有基于相同思想的其他算法?
正如在线性时间多数算法?的答案中所看到的,可以在线性时间和log(n)
空间中计算元素数组的大多数。
已经证明,每个看到这个算法的人都认为它是一种很酷的技术。但是这个想法是否推广到新算法呢?
似乎这个算法的隐藏力量在于保持一个起复杂作用的计数器 -- 例如“(目前大多数元素的计数) - (目前第二多数元素的计数)”。是否有基于相同思想的其他算法?
嗯,首先让我们了解一下算法为什么有效,以便于“隔离”这些思想。
该算法的关键是如果你有一个多数元素,那么你可以将其每个出现与“另一个”元素匹配,然后你就有了一些更多的“备用”。
所以,我们只需要一个计数器来计算我们客人答案的“备用”出现次数。如果它达到0,则它不是从我们“选举”“当前”元素作为主要客人元素到“当前”位置开始的子序列的大多数元素。此外,由于我们的“客人”元素匹配所考虑子序列中的每个其他元素出现,因此在所考虑的子序列中没有主要元素。
现在,由于:
很明显,通过反证法可以看出,如果存在主要元素,则我们有整个序列的后缀,在其中计数器永远不会归零。
现在:可以在新的O(1)大小O(n)时间算法中利用的想法是什么?
对我来说,每当你必须计算元素序列上的属性P时,就可以应用此技术,该序列:
在我们的情况下,P是我们“选举”的主要元素的“备用”出现次数,而Q是“P为零”。
如果您以这种方式看待事物,那么最长公共子序列也利用了相同的思想(关于其“酷炫因素”的问题我不确定)。
n/2
次的元素,其中n
是流的大小。您可以在O(n)
时间(带有微小的常数和O(log(n))
空间,最坏情况下并且高度不太可能)内完成此操作。
k
个最频繁的项目,每个项目在原始流中至少出现n/(k+1)
次。请注意,如果k=1,则最终得到原始问题。from collections import defaultdict
def majority_element_general(arr, k=1):
counter, i = defaultdict(int), 0
while len(counter) < k and i < len(arr):
counter[arr[i]] += 1
i += 1
for i in arr[i:]:
if i in counter:
counter[i] += 1
elif len(counter) < k:
counter[i] = 1
else:
fields_to_remove = []
for el in counter:
if counter[el] > 1:
counter[el] -= 1
else:
fields_to_remove.append(el)
for el in fields_to_remove:
del counter[el]
potential_elements = counter.keys()
# might want to check that they are really frequent.
return potential_elements
P
和Q
的一般描述听起来像是动态规划的描述。你是不是想说的比“Boyer-Moore 是一种动态规划算法”更多? - dsg