import java.util.Arrays;
/**
* 给定有序数组arr,代表X轴上的点,给定一个正整数K,代表长度为K的绳子,问绳子最多能盖住几个点(绳子边缘碰到也算盖住)
* <p>
* 滑动窗口
*/
public class CoverMostPoint {
/**
* 滑动窗口
*
* @param arr 数组
* @param k 长度
* @return 结果
*/
public static int coverMostPoint(int[] arr, int k) {
if (arr == null || arr.length == 0) {
return 0;
}
int left = 0;
int right = 0;
int max = 0;
int length = arr.length;
while (left < length) {
while (right < length && arr[right] - arr[left] <= k) {
right++;
}
max = Math.max(max, right - left);
left++;
}
return max;
}
/**
* 用二分法找到 绳子长度内最近的点的下标
*
* @param arr 数组
* @param L 长度
* @return 结果
*/
public static int coverMostPoint2(int[] arr, int L) {
int res = 1;
for (int i = 0; i < arr.length; i++) {
int nearest = nearestIndex(arr, i, arr[i] - L);
res = Math.max(res, i - nearest + 1);
}
return res;
}
public static int nearestIndex(int[] arr, int R, int value) {
int L = 0;
int index = R;
while (L <= R) {
int mid = L + ((R - L) >> 1);
if (arr[mid] >= value) {
index = mid;
R = mid - 1;
} else {
L = mid + 1;
}
}
return index;
}
/**
* 暴力解,找到以i为结尾,最长能盖住几个点
*
* @param arr 数组
* @param L 长度
* @return 结果
*/
public static int test(int[] arr, int L) {
int max = 0;
for (int i = 0; i < arr.length; i++) {
int pre = i - 1;
while (pre >= 0 && arr[i] - arr[pre] <= L) {
pre--;
}
max = Math.max(max, i - pre);
}
return max;
}
// for test
public static int[] generateArray(int len, int max) {
int[] ans = new int[(int) (Math.random() * len) + 1];
for (int i = 0; i < ans.length; i++) {
ans[i] = (int) (Math.random() * max);
}
Arrays.sort(ans);
return ans;
}
public static void main(String[] args) {
int len = 100;
int max = 1000;
int testTime = 100000;
System.out.println("测试开始");
for (int i = 0; i < testTime; i++) {
int k = (int) (Math.random() * max);
int[] arr = generateArray(len, max);
int ans1 = coverMostPoint(arr, k);
int ans2 = coverMostPoint2(arr, k);
int ans3 = test(arr, k);
if (ans1 != ans2 || ans2 != ans3) {
System.out.println("oops!");
break;
}
}
System.out.println("测试结束");
}
}
/* 如有意见或建议,欢迎评论区留言;如发现代码有误,欢迎批评指正 */