给定一个排序的int数组,找到log(n)中最常出现的元素

时间:2017-10-23 17:22:21

标签: algorithm search binary

很容易在O(n)中找到最常出现的元素。 是否有更快的算法(O(logn))来做到这一点? (给定数组已排序)

3 个答案:

答案 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