我正在为一维数组编写峰值查找算法的代码。我已阅读此帖Peak finding algorithm。这正是我想要做的,有关于时间复杂性的讨论,但没有任何类型的伪代码。问题:
给定一个数组
[a,b,c,d,e,f,g]
,其中a
到g
是数字,b
是一个峰值,当且仅当a<=b
和b>=c
时。
示例:给定数组{1,2,3,4,5,19,25,20}
,应返回索引6
。
边缘情况应该给出:
{100,4,3,1,19,20} -- index 0
{1,3,5,19,20} -- index 4
我已在Java
中实施。我当前的运行时间是O(n)
。我想知道这是否可以改善
public static int naive(int[] arr){
int l=arr.length;
if (arr[0]>=arr[1]) {
return 0;
}
if (arr[l-1]>arr[l-2]){
return l-1;
}
for (int i=1; i < arr.length-1;i++){
if (arr[i] >= arr[i-1] && arr[i] >= arr[i+1] ){
return i;
}
}
return -1;
}
答案 0 :(得分:2)
以下功能可能比您的更有效。请注意,这会找到 本地最大值 。
public static int findLocalMaximum(int[] arr){
int i = 0;
while(i + 1 < arr.length && arr[i+1] >= arr[i]) {
++i;
}
return i;
}
编辑:以下函数查找问题中定义的峰值。请注意,我在while循环中删除了边界检查,因为仅在arr[l-2] > arr[l-1]
时才会到达循环,因此while循环中的条件将为false并且将返回l-2
。
public static int findPeak(int[] arr){
int l = arr.length;
if(arr[0] >= arr[1]) {
return 0;
}
if(arr[l-1] >= arr[l-2]) {
return l-1;
}
int i = 1;
while(arr[i+1] > arr[i]) {
++i;
}
return i;
}
答案 1 :(得分:2)
如果我可以提出我的解决方案:
public static int findPeak(int[] array, int start, int end) {
int index = start + (end - start) / 2;
if (index - 1 >= 0 && array[index] < array[index - 1]) {
return findPeak(array, start, index - 1);
} else if (index + 1 <= array.length - 1 && array[index] < array[index + 1]) {
return findPeak(array, index + 1, end);
} else {
return array[index];
}
}
我认为在if语句中直接处理边缘情况更简单。我还测试了几个输入,它似乎工作。
答案 2 :(得分:0)
binary search-like algorithm
应该有效。采用divide and conquer
策略。由于您对single peak
感兴趣,因此您可以做的最好的事情是O(log n)
。但是如果你想找到所有的峰值,它至少会是O(n)
。
以下是divide-and conquer algorithm
:
public static int peak1D(int[] arr, int start, int end){
//edge cases
if (end-start==1){
if (start==0)
return start;
else
return end;
}
int i = start+end>>>1;
if (arr[i]<arr[i-1])
return peak1D(arr,start,i);
if (arr[i]<arr[i+1]){
return peak1D(arr, i, end);
}
else
return i;
}
我测试了几个输入,它似乎工作。我处理边缘情况并不是很好。虽然这是简单的推理
答案 3 :(得分:0)
假设Array是全局的,为了简单起见,你可以根据需要传递它。
private static int getPeak1D(int start,int end)
{
int x = (start+end)/2;
if( (x == 0 && array[x] >= array[x+1]) ||
(x == array.length-1 && array[x]>=array[x-1]) ||
(x>0 && x< array.length-1 && array[x] >= array[x-1] && array[x] >= array[x+1]))
return x;
if(x+1 < array.length && array[x] < array[x+1])
temp = getPeak1D(x+1,end);
if(temp > -1)
return temp;
if(x-1 > -1 && array[x] < array[x-1])
return getPeak1D(0,x-1);
else
return -1;
}
首先检查峰的第一个边,第二个边和内部。 如果没有找到峰值,如果array [x + 1]&gt; array [x],Second if将转到数组的右半部分。我们将它存储在temp(我将它作为全局)我们不返回它,因为如果数组[x + 1]和数组[x-1]都比数组[x]大,但右侧没有找到任何如果检查左侧,你应该去第三个
检查此背后的逻辑 https://courses.csail.mit.edu/6.006/spring11/rec/rec02.pdf