Arrays 查找数组中的局部极小值

Arrays 查找数组中的局部极小值,arrays,algorithm,binary-search,Arrays,Algorithm,Binary Search,给定一个整数数组,求局部极小值。如果A[i-1]>A[i]且A[i]1的值都相同。在这种情况下,没有一个元素可以是局部极小值,因为没有一个元素小于它的邻居。但是,为了确定所有值都相同,您必须查看所有数组元素,这需要O(n)个时间。如果使用的时间少于O(n),则不必查看所有数组元素 另一方面,如果保证数组元素是不同的,则可以使用以下观察结果在O(logn)时间内解决此问题: 如果只有一个元素,则保证为局部最小值 如果有多个元素,请查看中间的元素。如果是本地最小值,你就完了。否则,它旁边的至少一个元

给定一个整数数组,求局部极小值。如果A[i-1]>A[i]且A[i] 我知道如果只有一个局部极小值,那么我们可以用改进的二进制搜索来求解。
但是,如果已知数组中存在多个局部极小值,可以在
O(logn)
时间内求解吗?

局部极小值的数目可以是
n/2
;您不能在
O(logn)
时间内全部枚举它们。

如果不能保证数组元素是不同的,那么就不可能在O(logn)时间内进行枚举。原因如下:假设您有一个数组,其中所有n>1的值都相同。在这种情况下,没有一个元素可以是局部极小值,因为没有一个元素小于它的邻居。但是,为了确定所有值都相同,您必须查看所有数组元素,这需要O(n)个时间。如果使用的时间少于O(n),则不必查看所有数组元素

另一方面,如果保证数组元素是不同的,则可以使用以下观察结果在O(logn)时间内解决此问题:

  • 如果只有一个元素,则保证为局部最小值
  • 如果有多个元素,请查看中间的元素。如果是本地最小值,你就完了。否则,它旁边的至少一个元素必须小于它。现在,想象一下,如果从一个较小的元素开始,沿着远离中间元素的方向逐渐向数组的一端移动,会发生什么。在每一步中,要么下一个元素比上一个元素小,要么它会更大。最终,您将以这种方式到达数组的末尾,或者到达局部最小值。请注意,这意味着您可以这样做以找到局部最小值。然而,我们实际上不会这么做。相反,我们将使用在这一半数组中存在局部最小值这一事实作为丢弃一半数组的理由。在剩下的部分中,我们保证找到一个局部最小值
  • 因此,您可以建立以下递归算法:

  • 如果只有一个数组元素,那么它是一个局部最小值
  • 如果有两个数组元素,请检查每个元素。一个必须是本地最小值
  • 否则,请查看数组的中间元素。如果是本地最小值,则返回它。否则,至少一个相邻值必须小于此值。在包含较小元素的数组的一半中递归(但不在中间)
  • 请注意,这具有递归关系

    T(1)≤ 一,

    T(2)≤ 一,

    T(n)≤ T(n/2)+1

    使用主定理,您可以根据需要显示此算法在时间O(logn)内运行

    希望这有帮助


    还请注意,如果数组的边小于相邻元素,则此算法仅在数组的边计算为局部极小值时有效。

    您的算法将不适用于此数组

    15, 13, 12, 18, 19, 20, 7, 6, 5, 4, 3, 2, 1
    
    这里的局部最小值是12。。但当我检查中间元素7时,你的算法将丢弃左半部分(有最小值),并检查右半部分。因此它不起作用

    我认为它只适用于特殊情况,即数组具有特殊属性a[1]≥ A[2]和
    A[n]− 1] ≤ A[n]

    使用分治算法。设m=n/2,并检查值A[m](即 是数组中间的元素。< /P> 案例1:A[m]−1] 案例2:A[m+1]>A[m]。那么数组的右半部分必须包含一个局部最小值,所以 在右半部分递归。这与情况1是对称的

    案例3:A[m]− 1] >A[m]和A[m+1]运行时间递归为T(n)=T(n/2)+Θ(1),由此产生T(n)=Θ(logn)。

    原始问题不完整

    刚刚在找到完整的问题和完整详细的解释 ! - 不是我的博客

    给定一个唯一整数数组,其前两个数递减,后两个数递增,在数组中找到一个局部极小值。如果数组中的一个数同时小于其左数和右数,则称为局部极小值

    例如,在数组9,7,2,8,5,6,3,4中 2是一个局部极小值,因为它小于其左右数字7和8。同样,5是另一个局部极小值,因为它介于8和6之间,两者都大于5


    您需要找到任何一个局部极小值。

    这里有一个适用于O(logn)的解决方案。基本上,这适用于合并排序方法(分治)

    公共类LocalMaxima{
    int[]a={5,8,10,25,6,3,44,51,55,56,57,58,34,5,59};
    @试验
    public void localMaxima(){
    System.out.println((a[localMaxima(0,a.length-1)]);
    }
    int localMaxima(int低,int高){
    如果(高-低>2){
    int mid=(低+高)/2;
    返回maxof(localMaxima(低,中),localMaxima(中+1,高));
    }
    否则如果(高-低==1){
    返回最大值(高、低);
    }
    否则如果(高-低==0){
    高回报;
    }
    如果(高-低==2){
    返回maxof(maxof(低、高)、低+1);
    }
    返回0;
    }
    intmaxof(inti,intj){
    
    如果(a[i]实际上是我以前的算法
    public class LocalMaxima {
        int []a = {5,8,10,25,6,3,44,51,55,56,57,58,34,5,59};
    
        @Test 
        public  void localMaxima () {
            System.out.println((a[localMaxima(0,a.length-1)]));
        }
    
        int localMaxima(int low, int high) {
            if(high-low > 2) {
                int mid = (low+high)/2;
                return maxof(localMaxima(low,mid),localMaxima(mid+1, high));
            }
            else if(high-low == 1) {
                return maxof(high,low);
            }
            else if(high-low == 0) {
                return high;
            }
            if(high-low == 2) {
                return maxof(maxof(low, high),low+1);
            }
            return 0;
        }
    
        int maxof(int i, int j) {
            if(a[i] <a[j]) {
                return j;
            }
            else {
                return i;
            }
        }
    }
    
    public class LocalMaximas {
    
    @Test
    public void test () {
        System.out.println("maximas: please modify code to handle if array size is <= 2");
    
        int []a = {5,8,10,25,6,3,44,51,55,56,57,58,34,5,59,2};
        localMaximas(a);
    
        int []b = {9,7,2,8,5,6,3,4, 2}; //9,8,6,4
        localMaximas(b);
    
        int [] c= {15, 13, 12, 18, 19, 20, 7, 6, 5, 4, 3, 2, 1};//15,20
        localMaximas(c);
    }
    
    public  void localMaximas (int [] a) {
        System.out.println("\n\n");
        if(isMaxima(a,0)) {
            System.out.println(a[0]);
        }
        if(isMaxima(a,a.length-1)) {
            System.out.println(a[a.length-1]);
        }
        localMaximas(a,0,a.length-1);
    }
    
    int localMaximas(int []a,int low, int high) {
        int mid = (low+high)/2;
        if(high-low > 3) {     // more than 4 items in currently  divided array
            if(isMaxima(a,mid)) {
                System.out.println(a[mid]);
            }   
            localMaximas(a,low, mid);
            localMaximas(a,mid, high);
        }
        else if(high-low == 3){ //exactly 4 items in currently  divided array
            localMaximas(a,low, mid+1);
            localMaximas(a,mid, high);
        }   
        else if((high-low == 2) && (isMaxima(a,low+1))) {
            System.out.println(a[low+1]);
        }
        return 0;
    }
    
    int maxof(int []a, int i, int j) {
        if(a[i] <a[j]) {
            return j;
        }
        else {
            return i;
        }
    }
    
    boolean isMaxima(int []a ,int mid) {
        if(mid == 0) {
            if(maxof(a, mid, mid+1) == mid) {
                return true;
            }
            else {
                return false;
            }
        }
        else if(mid==a.length-1) {
            if(maxof(a,mid,mid-1) == mid) {
                return true;
            }
            else {
                return false;
            }
        }
        else {
            if((maxof(a, mid, mid+1) == mid) && (maxof(a, mid, mid-1) == mid)) {
                return true;
            }
            else {
                return false;
            }           
        }
    }
    }