如果有多个峰值,如何在数组中找到峰值元素?

时间:2017-08-16 12:36:55

标签: java arrays algorithm binary-search

对于具有单峰值元素的数组,可以使用二进制搜索在o(logn)中完成,但是如果数组中有多个峰值元素,我们应该使用哪种方法?

---提供更多信息---- 峰值元素比其邻居更大,例如,查看下面的数组,

[1,3,20,4,1,0,7,5,2]

其中有2个峰,20和7.

我们需要设计一种算法来查找此数组中的峰值元素。

6 个答案:

答案 0 :(得分:0)

我可能无法理解你的问题,因为找到单个峰值可以在O(logn)中完成,需要在第一个位置对数组进行排序。

我建议你存储一个差异数组,它会生成如下输出:[1,3,20,4,1,0,7,5,2] => [1, 1,-1,-1,-1, 1,-1,-1]只是生成一个大小为n - 1的数组,并将增加的方向放在数组中。这可以在O(n)单次通过中完成。

在第二遍中,您将寻找[1,-1]对,这是发生峰值的地方。

如果要在开头和结尾找到峰值,则需要检查start是否为-1,结束为1。

希望这有帮助。

答案 1 :(得分:0)

我们的想法是使用修改后的二进制搜索。

如果s -> [a], a s -> [c], c a -> [a], a a -> [b], b a -> [c], c b -> [b] b -> [b], b b -> [a], a b -> [c], c c -> [c], c c -> [a], a c -> [b], b ,则您的高峰总是存在于右半部分。

如果arr[mid+1]>arr[mid],则左半部分始终存在峰值。 因为arr [i + 1]只有两个选项,要么大于arr [i]要么小于arr [i-1]

我没有java实现,但这是一个python实现。

arr[mid-1]>arr[mid]

答案 2 :(得分:0)

用于查找具有多个峰的所有峰元素。

class Solution(object):
    def findPeakElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        left, right = 0, len(nums) - 1
        while left < right:
            mid = left + right >> 1
            if nums[mid] < nums[mid + 1]:
                left = mid + 1
            else:
                right = mid
        return left

答案 3 :(得分:0)

我最近在一个编程网站上遇到了类似的问题,但是除了发现峰值以外,还有另一个重要的限制。首先,可能有多个高峰,但也可能有高原!平稳是在arr中发生的事情:[1,2,2,2,1],在这种情况下,我们必须将峰返回为2。在问题中,我们还被要求返回峰的第一个位置发生,所以在这种情况下,它将是position =1。唯一需要注意的是arr:[1,2,2,2,3,4,5,1]中存在峰值在倒数第二个位置中有5个,但即使有一系列重复项在第一眼看上去都像高原一样,也没有高原。

所以我想到的基本算法是使用差异数组,正如使用{1,0,-1}所建议的那样,当在连续流中获得一系列重复项时,我们使用0。每当在检查差值数组时获得0时,我们就会开始寻找第一个非零条目(无论是1还是-1)并相应地输出。但是,我们再次要保持谨慎,可能是差分数组看起来像Diff = [-1,1,-1,1,0,0,0],在这种情况下没有平台,只有一个峰。当输入为arr时,python代码如下所示:

n = len(arr)
if arr == []:
    return {"pos":[],"peaks":[]}
Diff = []
for i in range(0,n-1):
    if arr[i]< arr[i+1]:
        Diff.append(1)
    elif arr[i] == arr[i+1]:
        Diff.append(0)
    if arr[i] > arr[i+1]:
        Diff.append(-1)
pos = []
peaks = []
j = 0
for i in range(0,n-2):
    if Diff[i] == 1 and Diff[i+1] == -1:
        pos.append(i+1)
        peaks.append(arr[i+1])
    if Diff[i] == 1 and Diff[i+1] == 0:
        if Diff[i+1:] == [Diff[i+1]]:
            break
        j = i+1
        while(Diff[j] == 0 and j < n-2):
            j = j+1
        if Diff[j] == -1:
            pos.append(i+1)
            peaks.append(arr[i+1])


return {"pos":pos, "peaks":peaks} 

答案 4 :(得分:0)

int arr[] = {50, 12, 13, 20, 16, 19, 11, 7, 24};
int size = sizeof(arr) / sizeof(arr[0]);

int peak_arr[size / 2];
int i, j, k = 0;
int next, previous = 0;

for(i = 0; i < size; i++){
    if(i + 1 == size){
        next = 0;
    }
    else{
        next = arr[i + 1];
    }
    
    if(arr[i] > next && arr[i] >= previous){
        peak_arr[k++] = arr[i];
    }
    previous = arr[i];
}

答案 5 :(得分:-1)

使用递归方法查找多个峰值元素。

def Div(lst, low, high):
    mid = (low + high)//2
    if low > high:
        return ""
    else:
        if mid+1 < len(lst) and lst[mid] > lst[mid+1] and lst[mid] > lst[mid -1]:
            return str(lst[mid]) + " " + Div(lst, low, mid-1) + Div(lst, mid+1, high)
        else:
            return Div(lst, low, mid-1) + Div(lst, mid + 1, high)

def peak(lst):
    if lst == []:
        return "list is empty"
    elif len(lst) in [1, 2]:
        return "No peak"
    else:
        return Div(lst, 0, len(lst))

print(peak([0, 5, 2, 9, 1, 10, 1]))