给定一个有数组arr,代表数轴上从左到右有
n个点arr[0],arr[1]…arr[n-1],给定一个长度为L的绳子求绳子最多能覆盖其中的几个点
方法一:枚举二分法
我们以绳子的右端点为参考对象,当右端点踩到第一个点时,数一下左边绳子范围里面有几个点,数的方法就是看有多少点的距离是大于等于左端点所表达的距离,通过这种方法可以保证有边不会套到不存在的点。
public static int maxPoint(int []arr,int L){
int res = 1;//包含点一个起步
for(int i = 0;i < arr.length;i++){//i是对应右边,遍历所有的点
int nearest = nearestIndex(arr,i,arr[i] - L);//arr[i] - L对应的是左点距离(相对于0位置)
res = Math.max(res,i - nearest + 1);//通过索引便知有几个点
}
return res;
}
public staitc int nearestIndex(int []arr,int R,int value){
int L = 0;//左
int index = R;
while(L < R){//二分开始
int mid = L + ((R - L)>>1);//取到L~R中点所对应的距离
if(arr[mid]>=value){
index = mid;
R = mid - 1;
}else{
L = mid + 1;
}
}
return index;
}
方法二:滑动窗口法
当绳子左边端点来到左边点时,右边端点受限于绳长范围地往右试探性的右走,就靠这种蠕动的尝试,来看着种范围下对应几个点,也就相当在一个可变长度的窗口中找点。这种方法保证了单调不递减地确定一个点,左右边界是无需回退的