【问题标题】:algorithm to find max and min in a increasing,decreasing, increasing and decreasing array在递增、递减、递增和递减数组中找到最大值和最小值的算法
【发布时间】:2012-01-02 02:15:21
【问题描述】:

给定一个数组,其中的值要么只增加,要么只减少或增加然后减少,如何找到这样的数组的最大值和最小值?

最小值只是最终值中的最小值。

但是如何找到最大值呢?

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

任何代码(在 java 中)都受到高度赞赏。

谢谢
诺西布

【问题讨论】:

    标签: java algorithm data-structures


    【解决方案1】:

    根据 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);
    }
    

    }

    【讨论】:

      【解决方案2】:

      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
      

      【讨论】:

        【解决方案3】:
        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]
        

        【讨论】:

        • 能否改进以处理重复键?
        • @allenylzhou 是的,它可以。在任何看到&lt;&gt; 的地方,不要与相邻元素进行比较,而是与下一个不同的元素进行比较。如果没有下一个元素不同,则比较的结果就是错误的。
        • @Jean-BernardPellerin 我认为如果每个元素都是相同的值,这将导致 O(n)。
        • @AT-Aoi 你是对的。我想不出任何解决最坏情况的方法 [1] = [2] = ... = [x-1] [1] = [x+1] = ... = [结束] 一个递增然后递减的序列,中间只有一个值的变化。在不搜索所有值的情况下,任何二分搜索都无法知道中间的哪一侧包含该点。
        【解决方案4】:

        通过二分查找,看看它属于哪种情况。本质上,尝试找到第一个枢轴点,其中有较大的元素紧随其后的是较小的元素,例如 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
        

        【讨论】:

          【解决方案5】:

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

          您确实可以在O(log n) 时间通过二分搜索找到它。在每次迭代中,检查导数是否为负。如果是,则向左移动,否则向右移动。

          【讨论】:

          • 或者只是x[i+1] &lt; x[i],但这无助于找到i的正确值。
          • @David:我的答案已经更新,详细说明如何找到它!
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-16
          • 1970-01-01
          相关资源
          最近更新 更多