You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
3.7 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class_2022_09_2_week;
// 来自微众银行
// 给定一个数字n代表数组的长度
// 给定一个数字m代表数组每个位置都可以在1~m之间选择数字
// 所有长度为n的数组中最长递增子序列长度为3的数组叫做达标数组
// 返回达标数组的数量
// 1 <= n <= 500
// 1 <= m <= 10
// 500 * 10 * 10 * 10
// 结果对998244353取模
// 实现的时候没有取模的逻辑,因为非重点
public class Code02_NLengthMValueLIS3 {
// 暴力方法
// 为了验证
public static int number1(int n, int m) {
return process1(0, n, m, new int[n]);
}
public static int process1(int i, int n, int m, int[] path) {
if (i == n) {
return lengthOfLIS(path) == 3 ? 1 : 0;
} else {
int ans = 0;
for (int cur = 1; cur <= m; cur++) {
path[i] = cur;
ans += process1(i + 1, n, m, path);
}
return ans;
}
}
public static int lengthOfLIS(int[] arr) {
if (arr == null || arr.length == 0) {
return 0;
}
int[] ends = new int[arr.length];
ends[0] = arr[0];
int right = 0;
int max = 1;
for (int i = 1; i < arr.length; i++) {
int l = 0;
int r = right;
while (l <= r) {
int m = (l + r) / 2;
if (arr[i] > ends[m]) {
l = m + 1;
} else {
r = m - 1;
}
}
right = Math.max(right, l);
ends[l] = arr[i];
max = Math.max(max, l + 1);
}
return max;
}
// i : 当前来到的下标
// f、s、t : ends数组中放置的数字
// ? == 0没放
// n : 一共的长度!
// m : 每一位都可以在1~m中随意选择数字
// 返回值i..... 有几个合法的数组!
public static int zuo(int i, int f, int s, int t, int n, int m) {
if (i == n) {
return f != 0 && s != 0 && t != 0 ? 1 : 0;
}
// i < n
int ans = 0;
for (int cur = 1; cur <= m; cur++) {
if (f == 0 || f >= cur) {
ans += zuo(i + 1, cur, s, t, n, m);
} else if (s == 0 || s >= cur) {
ans += zuo(i + 1, f, cur, t, n, m);
} else if (t == 0 || t >= cur) {
ans += zuo(i + 1, f, s, cur, n, m);
}
}
return ans;
}
// 正式方法
// 需要看最长递增子序列!
// 尤其是理解ends数组的意义
public static int number2(int n, int m) {
int[][][][] dp = new int[n][m + 1][m + 1][m + 1];
for (int i = 0; i < n; i++) {
for (int f = 0; f <= m; f++) {
for (int s = 0; s <= m; s++) {
for (int t = 0; t <= m; t++) {
dp[i][f][s][t] = -1;
}
}
}
}
return process2(0, 0, 0, 0, n, m, dp);
}
public static int process2(int i, int f, int s, int t, int n, int m, int[][][][] dp) {
if (i == n) {
return f != 0 && s != 0 && t != 0 ? 1 : 0;
}
if (dp[i][f][s][t] != -1) {
return dp[i][f][s][t];
}
int ans = 0;
for (int cur = 1; cur <= m; cur++) {
if (f == 0 || cur <= f) {
ans += process2(i + 1, cur, s, t, n, m, dp);
} else if (s == 0 || cur <= s) {
ans += process2(i + 1, f, cur, t, n, m, dp);
} else if (t == 0 || cur <= t) {
ans += process2(i + 1, f, s, cur, n, m, dp);
}
}
dp[i][f][s][t] = ans;
return ans;
}
public static void main(String[] args) {
System.out.println("功能测试开始");
for (int n = 4; n <= 8; n++) {
for (int m = 1; m <= 5; m++) {
int ans1 = number1(n, m);
int ans2 = number2(n, m);
if (ans1 != ans2) {
System.out.println(ans1);
System.out.println(ans2);
System.out.println("出错了!");
}
}
}
System.out.println("功能测试结束");
System.out.println("性能测试开始");
int n = 2000;
int m = 20;
System.out.println("序列长度 : " + n);
System.out.println("数字范围 : " + m);
long start = System.currentTimeMillis();
number2(n, m);
long end = System.currentTimeMillis();
System.out.println("运行时间 : " + (end - start) + " 毫秒");
System.out.println("性能测试结束");
}
}