Java 求递增、递减、递增和递减数组中最大值和最小值的算法

Java 求递增、递减、递增和递减数组中最大值和最小值的算法,java,algorithm,data-structures,Java,Algorithm,Data Structures,给定一个数组,该数组中的值要么是递增的,要么是递减的,要么是先递增后递减的,如何求该数组的最大值和最小值 最小值只是最小的结束值 但是如何找到最大值呢 一种方法是运行时间为O(n)的线性方法,通过对二进制搜索进行一些修改,可以在O(logn)中解决这个问题吗 任何代码(java)都非常受欢迎 谢谢 诺西比在斜率最多从增加到减少一次的情况下,最大值出现在导数第一次变为负值时。换句话说,x[i]是满足(x[i+1]-x[i])

给定一个数组,该数组中的值要么是递增的,要么是递减的,要么是先递增后递减的,如何求该数组的最大值和最小值

最小值只是最小的结束值

但是如何找到最大值呢

一种方法是运行时间为O(n)的线性方法,通过对二进制搜索进行一些修改,可以在O(logn)中解决这个问题吗

任何代码(java)都非常受欢迎

谢谢

诺西比

在斜率最多从增加到减少一次的情况下,最大值出现在导数第一次变为负值时。换句话说,
x[i]
是满足
(x[i+1]-x[i])<0
i
最小值的最大值


您确实可以在
O(logn)
time中通过二进制搜索找到这一点。在每次迭代中,检查导数是否为负。如果是,则向左移动,否则向右移动。

如果斜率最多从增大到减小一次,则最大值出现在导数第一次变为负值时。换句话说,
x[i]
是满足
(x[i+1]-x[i])<0
i
最小值的最大值


您确实可以在
O(logn)
time中通过二进制搜索找到这一点。在每次迭代中,检查导数是否为负。如果是,则向左移动,否则向右移动。

通过二进制搜索,查看它属于哪种情况。基本上,试着找到第一个轴心点,即较大的元素紧跟较小的元素(如p1),以及第一个轴心点,即较小的元素紧跟较大的元素(如p2)。这两种方法都可以通过二进制搜索实现(谷歌搜索旋转排序数组中的二进制搜索)

如果p1存在,p2不存在,它是一个递增序列(min=a[0]max=a[n])

如果p2存在而p1不存在,则为递减顺序(min=a[n]max=a[0])

如果两者都存在,则其增加和减少

min = min(a[0],a[n]) \\first and last
max = a[p1] \\first point where bigger element is followed by a smaller one

通过二进制搜索,查看它属于哪种情况。基本上,试着找到第一个轴心点,即较大的元素紧跟较小的元素(如p1),以及第一个轴心点,即较小的元素紧跟较大的元素(如p2)。这两种方法都可以通过二进制搜索实现(谷歌搜索旋转排序数组中的二进制搜索)

如果p1存在,p2不存在,它是一个递增序列(min=a[0]max=a[n])

如果p2存在而p1不存在,则为递减顺序(min=a[n]max=a[0])

如果两者都存在,则其增加和减少

min = min(a[0],a[n]) \\first and last
max = a[p1] \\first point where bigger element is followed by a smaller one
如果[1]<[2]
如果[end-1]<[end]
最小=[1]
max=[结束]
其他的
最小值=最小值([1],[end])
max=binarysearch()
其他的
最小=[结束]
max=[1]
二进制搜索:
以中间元素[mid]为例
如果[mid-1]<[mid]<[mid+1]
二进制搜索[中间端]
如果[mid-1]>[mid]>[mid+1],则为else
二进制搜索[开始-中间]
其他的
返回最大值([mid-1]、[mid]、[mid+1]
如果[1]<[2]
如果[end-1]<[end]
最小=[1]
max=[结束]
其他的
最小值=最小值([1],[end])
max=binarysearch()
其他的
最小=[结束]
max=[1]
二进制搜索:
以中间元素[mid]为例
如果[mid-1]<[mid]<[mid+1]
二进制搜索[中间端]
如果[mid-1]>[mid]>[mid+1],则为else
二进制搜索[开始-中间]
其他的
返回最大值([mid-1]、[mid]、[mid+1]
An将执行您想要的操作。它可以在O(lgn)中找到任何订单统计信息,包括最小和最大值。形成树的成本为O(nlgn),这与最佳比较排序的复杂性相同。添加或删除元素的成本也为O(lgn)

下面是一个指向订单统计树的java实现的链接()

然而,根据您所述的假设,如您所示,最小值可以在O(1)中找到。最大值可以在O(lgn)中找到。以下是psedou代码:

findMax(array,n,m)
  middle = (n + m) / 2;

  //check for short array (length 1 or 2) to avoid indexing errors
  if middle == n && array(middle) > array(m)
    return(array(middle));
  else
    return(array(m));

  if array(middle) > array(middle - 1) //left side of peak
    if array(middle) < array(middle + 1) //at peak
      return(array(middle));
    else
      return(findMax(array(middle,m)); //peak is to the right
  else //right side of peak
    return(findMax(array,n,middle); //peak is to the left
findMax(数组,n,m)
中间=(n+m)/2;
//检查短数组(长度1或2)以避免索引错误
如果中间==n&&数组(中间)>数组(m)
返回(数组(中间));
其他的
返回(数组(m));
如果数组(中间)>数组(中间-1)//峰值左侧
如果数组(中间)<数组(中间+1)//处于峰值
返回(数组(中间));
其他的
return(findMax(数组(中间,m));//峰值在右边
else//山顶右侧
return(findMax(数组,n,中间);//峰值在左边
An将执行您想要的操作。它可以在O(lgn)中找到任何订单统计信息,包括最小和最大值。形成树的成本为O(nlgn),这与最佳比较排序的复杂性相同。添加或删除元素的成本也为O(lgn)

下面是一个指向订单统计树的java实现的链接()

然而,根据您所述的假设,如您所示,最小值可以在O(1)中找到。最大值可以在O(lgn)中找到。以下是psedou代码:

findMax(array,n,m)
  middle = (n + m) / 2;

  //check for short array (length 1 or 2) to avoid indexing errors
  if middle == n && array(middle) > array(m)
    return(array(middle));
  else
    return(array(m));

  if array(middle) > array(middle - 1) //left side of peak
    if array(middle) < array(middle + 1) //at peak
      return(array(middle));
    else
      return(findMax(array(middle,m)); //peak is to the right
  else //right side of peak
    return(findMax(array,n,middle); //peak is to the left
findMax(数组,n,m)
中间=(n+m)/2;
//检查短数组(长度1或2)以避免索引错误
如果中间==n&&数组(中间)>数组(m)
返回(数组(中间));
其他的
返回(数组(m));
如果数组(中间)>数组(中间-1)//峰值左侧
如果数组(中间)<数组(中间+1)//处于峰值
返回(数组(中间));
其他的
return(findMax(数组(中间,m));//峰值在右边
else//山顶右侧
return(findMax(数组,n,中间);//峰值在左边

根据Jean-Bernard Pellerin提出的逻辑

(在此代码中仅找到最大值)

递增递减数组中的公共类最大值
{
公共静态整数最大值(整数a、整数b、整数c)
{
int maxi=-1;
如果(a>maxi)
maxi=a;
如果(b>maxi)
maxi=b;
如果(c>maxi)
maxi=c;
返回最大值;
}
公共静态无效chkmax(整数a[],整数低,整数高)
{
int mid=(低+高)/2;
如果(低==高)
{
System.out.println(a[低]);
返回;
}
如果(低+1==高)
{
System.out.pri