【发布时间】:2012-01-02 02:15:21
【问题描述】:
给定一个数组,其中的值要么只增加,要么只减少或增加然后减少,如何找到这样的数组的最大值和最小值?
最小值只是最终值中的最小值。
但是如何找到最大值呢?
一种方法是运行时间为 O(n) 的线性方法,这可以通过对二分搜索进行一些修改在 O(logn) 中解决吗?
任何代码(在 java 中)都受到高度赞赏。
谢谢
诺西布
【问题讨论】:
标签: java algorithm data-structures
给定一个数组,其中的值要么只增加,要么只减少或增加然后减少,如何找到这样的数组的最大值和最小值?
最小值只是最终值中的最小值。
但是如何找到最大值呢?
一种方法是运行时间为 O(n) 的线性方法,这可以通过对二分搜索进行一些修改在 O(logn) 中解决吗?
任何代码(在 java 中)都受到高度赞赏。
谢谢
诺西布
【问题讨论】:
标签: java algorithm data-structures
根据 Jean-Bernard Pellerin 提出的逻辑
(此代码中仅找到最大值)
public class max_in_increasing_decreasing_array
{
public static int max (int a,int b,int c)
{
int maxi=-1;
if(a>maxi)
maxi=a;
if(b>maxi)
maxi=b;
if(c>maxi)
maxi=c;
return maxi;
}
public static void chkmax(int a[],int low,int high)
{
int mid=(low+high)/2;
if(low==high)
{
System.out.println(a[low]);
return;
}
if(low+1==high)
{
System.out.println(max(a[low],a[high],-1));
return;
}
if((a[mid-1]< a[mid]) && (a[mid] < a[mid+1]))
{
chkmax(a, mid+1, high);
}
else if((a[mid-1]> a[mid]) && (a[mid] > a[mid+1]))
{
chkmax(a, low, mid-1);
}
else
System.out.println(max(a[mid-1],a[mid],a[mid+1]));
}
public static void main(String[] args)
{
int a[]={6,7,4,3,2,1};
chkmax(a, 0,a.length-1);
}
}
【讨论】:
order-statistic tree 会做你想做的事。它可以在 O(lgn) 中找到任何顺序统计量,包括最小值和最大值。形成树的成本为 O(nlgn),与最佳比较排序的复杂度相同。添加或删除元素也会花费 O(lgn)。
这是一个链接 (OrderStatisticTree.java) 到一个订单统计树的 java 实现。
但是,根据您所陈述的假设,您可以在 O(1) 中找到最小值。最大值可以在 O(lgn) 中找到。这是伪代码:
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
【讨论】:
if [1] < [2]
if [end-1] < [end]
min = [1]
max = [end]
else
min = min([1],[end])
max = binarysearch()
else
min = [end]
max = [1]
binarysearch:
take the middle element [mid]
if [mid-1] < [mid] < [mid+1]
binary search [mid - end]
else if [mid-1] > [mid] > [mid+1]
binary search [start - mid]
else
return max([mid-1],[mid],[mid+1]
【讨论】:
< 或> 的地方,不要与相邻元素进行比较,而是与下一个不同的元素进行比较。如果没有下一个元素不同,则比较的结果就是错误的。
通过二分查找,看看它属于哪种情况。本质上,尝试找到第一个枢轴点,其中有较大的元素紧随其后的是较小的元素,例如 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
【讨论】:
在斜率从增加到减少最多一次的情况下,最大值出现在导数第一次变为负值时。换句话说,x[i] 是满足(x[i+1] - x[i]) < 0 的i 的最小值的最大值。
您确实可以在O(log n) 时间通过二分搜索找到它。在每次迭代中,检查导数是否为负。如果是,则向左移动,否则向右移动。
【讨论】:
x[i+1] < x[i],但这无助于找到i的正确值。