数组切分-蓝桥杯

目录

    • 题意以及判断
    • dfs 骗分
    • dfs 剪汁儿
    • 从底向上循环

题意以及判断

连续子数组,这是重点哈,连续子数组我总结了以下几个性质:

  1. 两层for可以枚举所有的连续子数组,也可以dfs,看情况吧,如果是dfs可能会爆栈。
  2. 乘法性质:
    比如:[1,2,3,4,5],元素1所在的连续子数组的数量有15。2所在的子数组数量有24=8,自己算算找规律。

如何判断子数组内部连续?

  1. 可以先排序,然后在循环判断,大概O(logk+k) ,1 <= k <= n
  2. 公差为1情况下,如果等差数列长度为n,那么会有一个结论,既max - min = n - 1,O(1)时间判断等差数列。
  3. 求和公式 a1*n + n * (n-1) /2 ,也是O(1)时间复杂度。

dfs 骗分

这里我们只拿前30%,骗一下分, 剩下的给随机数看老天爷吧。


import java.util.Random;
import java.util.Scanner;
public class Main {

    static int N, MOD = (int)1e9+7;
    static int[] arrays;

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        N = scan.nextInt();
        arrays = new int[N];
        for (int i = 0; i < N; i++) {
            arrays[i] = scan.nextInt();
        }
        if (N <= 20) System.out.println(dfs(0));
        else System.out.println(new Random().nextInt(10000));
        scan.close();
    }

    static int dfs(int u) {
        if (u >= N) return 1;
        int res = 0,
                min = Integer.MAX_VALUE;
        int sum = 0;
        for (int i = u; i < N; i++) {
            if (arrays[i] < min) min = arrays[i];
            sum += arrays[i];
            int n = i - u + 1;
            int q = min*n + n*(n-1)/2;
            if (q == sum) {
                res += dfs(i + 1);
                res %= MOD;
            }
        }
        return res;
    }
}

dfs 剪汁儿


import java.util.Arrays;
import java.util.Scanner;
public class Main__ {

    static int N, MOD = (int)1e9+7;
    static int[] arrays, cache;

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        N = scan.nextInt();
        arrays = new int[N];
        cache = new int[N + 1];
        for (int i = 0; i < N; i++) {
            arrays[i] = scan.nextInt();
        }
        Arrays.fill(cache, -1);
        System.out.println(dfs(0));
        System.out.println(Arrays.toString(cache));
        scan.close();
    }

    static int dfs(int u) {
        if (u >= N) return 1;
        int res = 0,
                min = Integer.MAX_VALUE,
                max = Integer.MIN_VALUE;
        for (int i = u; i < N; i++) {
            if (arrays[i] > max) max = arrays[i];
            if (arrays[i] < min) min = arrays[i];
            if (max - min == i - u) {
                res += cache[i + 1] > -1 ? cache[i + 1] : dfs(i + 1);
                res %= MOD;
            }
        }
        cache[u] = res;
        return res;
    }
}

从底向上循环

这个也是剪汁儿


import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int[] arrays = new int[n];
        for (int i = 0; i < n; i++) {
            arrays[i] = scan.nextInt();
        }

        int MOD = (int) 1e9+7;
        int[] cache = new int[n + 1];
        cache[n] = 1;
        for (int i = n - 1; i >= 0; i--) {
            int min = Integer.MAX_VALUE;
            int res = 0, sum = 0;
            for (int j = i; j < n; j++) {
                if (arrays[j] < min) min = arrays[j];
                sum += arrays[j];
                int l = j - i + 1;
                int q = min*l + l*(l-1)/2;
                if (q == sum) {
                    res += cache[j + 1];
                    res %= MOD;
                }
            }
            cache[i] = res;
        }

        System.out.println(cache[0]);

        scan.close();
    }
}

你可能感兴趣的:(蓝桥杯,java,算法)