查找阵列中峰元素的最佳算法

时间:2018-08-29 14:52:08

标签: arrays algorithm

到目前为止,我还没有找到解决该任务的算法:“一个元素是 当且仅当(A[i]>A[i+1])&&(A[i]>A[i-1])不是时,才视为峰值 考虑到array(1D)的边缘。”

我知道解决此问题的常用方法是使用“分而治之”,但这是在将边缘视为“峰”的情况下。

此练习需要获得的O(..)复杂度为 O(log(n))

sample arrays

通过上面的图片,我很清楚为什么它是O(log(n)),但是没有将边缘复杂度更改为O(n),因为在下面的图片中我递归运行 函数在中间元素的每一侧都起作用,这使其在O(n)中运行(最坏的情况是元素靠近边缘)。在这种情况下,为什么不使用像这样的简单二进制搜索:

public static int GetPeak(int[]A)
    {

        if(A.length<=2)//doesn't apply for peak definition
        {
            return -1;
        }
        else {

        int Element=Integer.MAX_VALUE;//The element which is determined as peak

        // First and Second elements can't be hills
        for(int i=1;i<A.length-1;i++)
        {
            if(A[i]>A[i+1]&&A[i]>A[i-1])
            {
                Element=A[i];
            break;
            }
            else
            {
                Element=-1;
            }

        }
        return Element;
        }

常见算法写在这里:http://courses.csail.mit.edu/6.006/spring11/lectures/lec02.pdf,但是正如我之前所说,它不适用于本练习的条款。

仅返回一个峰,否则返回-1。

此外,如果由于语言障碍(我不是英语为母语的人),该帖子措辞不当,我深感抱歉。

2 个答案:

答案 0 :(得分:0)

我认为您正在寻找一种利用分而治之的动态编程方法。本质上,您将拥有一个默认值的峰值,当您发现一个默认值时,它将被覆盖。如果您可以检查方法的开头并仅在未找到峰的情况下运行操作,则您的O()表示法类似于<div ref="{refName}">Hello!</div> ,其中O(pn)是给定值的概率数组的元素是一个峰,这是一个可变术语,因为它与数据的结构(或不)相关。例如,如果您的数组仅具有1到5之间的值,并且它们的分布均匀,则该概率将等于0.24,因此您希望算法在p中运行。请注意,这似乎仍然等同于O(0.24n)。但是,如果您要求数组中的数据值唯一,那么您的概率就等于:

O(n)

所以,这似乎很多,但是如果我们在p = 2 * sum( [ choose(x - 1, 2) for x in 3:n ] ) / choose(n, 3) p = 2 * sum( [ ((x - 1)! / (2 * (x - 3)!)) for x in 3:n ] ) / (n! / (n - 3)!) p = sum( [ (x - 1) * (x - 2) for x in 3:n ] ) / (n * (n - 1) * (n - 2)) p = ((n * (n + 1) * (2 * n + 1)) / 6 - (n * (n + 1)) + 2 * n - 8) / (n * (n - 1) * (n - 2)) p = ((1 / 3) * n^3 - 5.5 * n^2 + 6.5 * n - 8) / (n * (n - 1) * (n - 2)) 接近无穷大时取极限,那么n的值将接近1/3。

因此,如果我们有33%的机会在数组中的任何元素上找到峰,那么当您有1/3的概率找到峰时,则在递归的最低级别。因此,在找到一个比较之前,此值的期望值约为3个比较,这意味着时间恒定。但是,在进行比较之前,您仍必须先到达递归的最底层,这需要p时间。因此,在一般情况下,分治法应该在O(log(n))时间内运行,而在最坏的情况下,O(log(n))应该运行。

答案 1 :(得分:0)

如果您不能对数据做任何假设(数字序列的单调性,峰数),并且如果边缘不能算作峰,那么您就无法希望获得比O(n)更好的平均性能。您的数据是随机分布的,任何值都可以是峰值。您必须一一检查它们,并且值之间没有关联。

接受边缘作为潜在的峰候选者会改变一切:您知道总是会有至少一个峰,并且一个足够好的策略是始终朝增加值的方向搜索,直到您开始下降或到达边缘(这是您提供的文档之一)。该策略为O(nlog(n)),因为您使用二进制搜索来查找局部最大值。