很容易在O(n)中找到最常出现的元素。 是否有更快的算法(O(logn))来做到这一点? (给定数组已排序)
答案 0 :(得分:9)
这是不可能的。下面不是一个严格的证据(严格的下限证明一般很难)但是理智的推理。
假设您的数组始终为1, 2, 3, 4, 5, 6, ..., n
。然后用一个前一个数字1, 2, 3, 3, 5, ... n
替换一些数字。现在所有a[i] = i
的新数组i
除了一个位置外。
为了找到最常见的元素,您必须检查所有位置并检查那里的不规则性。请注意,只有一个不规则性,如果你查看数组的任何其他元素,你可以不说它的位置。因此,这个问题并不比在1和0的布尔数组中找到one
容易,这需要线性时间。
答案 1 :(得分:1)
不是O(logn)
但如果不同整数的数量较少,则可以在O(mlogn)
中求解,其中m是不同整数的总数。
必须注意的是,只有m << n
。
我们的想法是从索引0开始,找到排序数组中最后一次出现的相同数字,这可以通过跳过delta d来完成,就像你的采访者所说的那样,每次增加这个增量,直到你找到了最后一个号码。
在找到它之后,你可以拥有另一个变量maxCount
,它在开始时被初始化为0。检查是否endIndex - startIndex > maxCount
,如果是,请将maxCount
替换为endIndex - startIndex
。现在,从startIndex+1
开始重复相同的过程。
正如@ivan上面提到的,如果所有数字都不同,这将失败并且会给出O(n)解决方案。
答案 2 :(得分:0)
根据@Parijat的回答,这段Python代码可以在O(mlogn)
时间内完成。
import bisect
def most_frequent_in_sorted(lst):
most_frequent = None
max_frequency = 0
n = len(lst)
idx = 0
while idx < n:
# Get leftmost index holding an element != lst[idx]
next_leftmost_idx = bisect.bisect_right(lst, lst[idx])
# Update most frequent element
cur_frequency = next_leftmost_idx - idx
if cur_frequency > max_frequency:
most_frequent = lst[idx]
max_frequency = cur_frequency
# Update index to hold next different integer
idx = next_leftmost_idx
return most_frequent