算法笔记3——中级

127 阅读1分钟

第一课

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。然后.......