第一课
1、绳覆盖点
给定一个有序数组arr,代表数轴上从左到右有n个点arr[0]、arr[1]...arr[n-1],给定一个正数L,代表一根长度为L的绳子,求绳子最多能覆盖其中的几个点。
- 常规方式,时间复杂度是O(n * L)
- 优化的方式是类似滑动窗口的感觉,动态维护左右端点,时间复杂度是n!
- 两种代码记录如下
public static int f(int[] arr, int l) {
int max = 0;
int num = 0;
int a = -1;//左端点
int b = a;//右端点
for (int i = 0; i < arr.length; i++) {
a = i;
if (num != 0) {
num--;
}
while (b < arr.length) {
if (b < arr.length - 1 && arr[b + 1] - arr[a] <= l) {
num++;
b++;
} else {
break;
}
}
if (num > max) {
max = num;
}
}
return max;
}
// 此为官方答案
// 长度为L的绳子最多覆盖几个点,请保证arr有序
public static int maxPoint(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;
}
// 在arr[0..R]范围上,找满足>=value的最左位置
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;
}
2、袋子装苹果
小虎去附近的商店买苹果,商贩只提供6个每袋和8个每袋的包装包装不可拆分。可是小虎现在只想购买恰好n个苹果,小虎想购买尽量少的袋数方便携带。如果不能购买恰好n个苹果,小虎将不会购买。
输入一个整数n,表示小虎想购买的个苹果,返回最小使用多少袋子。如果无论如何都不能正好装下,返回-1。
- 传统方式,先用n除8得到袋子数,假如不能整除,则袋子数减1,看剩余是否能用6号袋子来装,循环......
- 穷举法!会发现最终答案8位一跳,奇数-1。然后.......