Java 求给定阵列的一维峰值
我正在为一维数组的峰值查找算法编写代码。我读过这篇文章。这正是我想做的,有关于时间复杂性的讨论,但没有类似伪代码的内容。问题是: 给定数组Java 求给定阵列的一维峰值,java,arrays,algorithm,Java,Arrays,Algorithm,我正在为一维数组的峰值查找算法编写代码。我读过这篇文章。这正是我想做的,有关于时间复杂性的讨论,但没有类似伪代码的内容。问题是: 给定数组[a,b,c,d,e,f,g]其中a到g是数字,b当且仅当a=c时为峰值 示例:给定数组{1,2,3,4,5,19,25,20},应返回索引6。 边缘案例应给出: {100,4,3,1,19,20}--索引0 {1,3,5,19,20}--索引4 我已经在Java中实现了。我当前的运行时间是O(n)。我想知道这是否可以改进 public static int
[a,b,c,d,e,f,g]
其中a
到g
是数字,b
当且仅当a=c
时为峰值
示例:给定数组{1,2,3,4,5,19,25,20}
,应返回索引6
。
边缘案例应给出:
{100,4,3,1,19,20}--索引0
{1,3,5,19,20}--索引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;
}
publicstaticint-naive(int[]arr){
int l=阵列长度;
如果(arr[0]>=arr[1]){
返回0;
}
如果(arr[l-1]>arr[l-2]){
返回l-1;
}
对于(int i=1;i=arr[i-1]&&arr[i]>=arr[i+1]){
返回i;
}
}
返回-1;
}
A类似于二进制搜索的算法应该可以工作。它采用了
分而治之的策略。由于您对单峰
感兴趣,因此最好是O(logn)
。但是如果你想找到所有的峰值,它至少是O(n)
以下是分治算法
:
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;
}
public static int peak1D(int[]arr,int start,int end){
//边缘案例
如果(结束-开始==1){
如果(开始==0)
返回启动;
其他的
返回端;
}
int i=开始+结束>>>1;
if(arr[i]以下函数可能比您的函数效率稍高。请注意,这将找到一个局部最大值
public static int findLocalMaximum(int[] arr){
int i = 0;
while(i + 1 < arr.length && arr[i+1] >= arr[i]) {
++i;
}
return i;
}
如果我可以提出我的解决办法:
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];
}
}
公共静态int findPeak(int[]数组,int start,int end){
int index=start+(end-start)/2;
如果(索引-1>=0&&array[index] }否则,如果(索引+1假设数组是全局的,为简单起见,您可以根据需要传递它
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;
}
private static int getPeak1D(int start,int end)
{
int x=(开始+结束)/2;
if((x==0&&array[x]>=array[x+1])||
(x==array.length-1&&array[x]>=array[x-1])||
(x>0&&x=数组[x-1]&&array[x]>=数组[x+1]))
返回x;
if(x+1-1)
返回温度;
if(x-1>-1&&array[x]
第一条if检查第一条边、第二条边和内部是否有峰值。
如果没有找到峰值,如果数组[x+1]>array[x],第二个if将进入数组的右半部分。我们将其存储在temp中(我将其作为全局设置),我们不会返回它,因为如果数组[x+1]和数组[x-1]都比数组[x]大,但右侧没有找到任何峰值,则应转到第三个if以检查左侧
检查一下这背后的逻辑
可以使用分治算法进行编码,这将给出O(logn)
@user1988876:这将如何工作,我需要遍历整个数组以找到峰值。因此时间复杂度必须是O(n)你感兴趣的是找到一个单峰,而不是所有的峰。为了更好地理解它,如果你有一个值为[ 5,5,5,7,2]的数组,你认为第二个5是一个峰值吗?@乔治:第二个是峰值(因为> =)。对不起,我不确定这是否行得通。或者可能是我理解得不清楚。你能给我一个伪代码让我试试吗?@EartoLearn:给我几分钟,我正在处理it@Marichyasana:当我说像
@user1988876这样的二进制搜索时,我的意思是
分而治之
,试试{3,2,1,0,5,4}
。不起作用。问题是无法通过查看中间来判断上半部分或下半部分是否存在局部峰值。要查找局部峰值,必须按顺序查看整个阵列,直到找到一个或到达末端。此算法有效,因为边缘情况(arr[0],arr[n-1])允许。start+(end-start)/2
可以简化为(start+end)/2
@RoyLee,start+(end-start)/2
避免溢出。
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;
}