利用1.1.18的思想,首先判断数组中是否存在局部极大值,
如果不存在,说明数组单调,不是bitnoic
如果存在,在局部极大值划分开的两部分分别判断是否存在局部极小,若左半部分存在局部极小,表明左半部分不是单调递增;若右半部分存在局部极小,表明右半部分不是单调递减
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
public class E1_4_20 {
public static void main(String[]args){
//测试局部极大值程序
int[]a={1,2,3,4,5,0};
int index=LocalMaximum(a);
StdOut.println("index="+index);
//测试程序
StdOut.println(isBitnoic(a));//a是
int[]b={1,2,3,4,5,0,1};
StdOut.println(isBitnoic(b));//b不是
//Doubling Ratio test
int N=125;
double prev=timeTrial(N);
for (N=250;true;N+=N){
double now=timeTrial(N);
StdOut.printf("N=%10d time=%7.5f ratio=%6.5f\n",N,now,now/prev);
prev=now;
}
}
public static double timeTrial(int N){
int MAX=1000000;
int[]a=new int[N];
for (int i=0;i<N;i++)
a[i]= StdRandom.uniform(-MAX,MAX);
StopWatch time=new StopWatch();
boolean isbitnoic=isBitnoic(a);
double res=time.elapsedTime();
return res;
}
public static boolean isBitnoic(int[]a){
int maxIndex=LocalMaximum(a);
if (maxIndex==-1) return false;//不存在局部极大值
if (LocalMinimum(a,0,maxIndex)!=-1||LocalMinimum(a,maxIndex,a.length-1)!=-1)
//极大值划分开的两部分只要有一个存在局部极小值,表明那部分不是单调的
return false;
else
return true;
}
public static int LocalMaximum(int[]a){
int lo=0;
int hi=a.length-1;
while (lo<hi){
int mid=(lo+hi)/2;
if (mid-1<0||mid+1>=a.length)
return -1;
if (a[mid]<a[mid-1]) hi=mid-1;
else if (a[mid]<a[mid+1]) lo=mid+1;
else return mid;
}
return -1;
}
public static int LocalMinimum(int[]a,int left,int right){
//判断数组a的lo到hi区域是否存在局部极小值
int lo=left;
int hi=right;
while (lo<hi){
int mid=(lo+hi)/2;
if (mid-1<left||mid+1>right) return -1;
if (a[mid]>a[mid-1]) hi=mid-1;
else if (a[mid]>a[mid+1]) lo=mid+1;
else return mid;
}
return -1;
}
}