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.

163 lines
4.0 KiB

2 years ago
package class_2022_05_3_week;
// 来自京东
// 4.2笔试
// 给定一个数组arr长度为Narr中所有的值都在1~K范围上
// 你可以删除数字目的是让arr的最长递增子序列长度小于K
// 返回至少删除几个数字能达到目的
// N <= 10^4K <= 10^2
public class Code02_RemoveNumbersNotIncreasingAll {
// 暴力方法
// 为了验证
public static int minRemove1(int[] arr, int k) {
return process1(arr, 0, new int[arr.length], 0, k);
}
public static int process1(int[] arr, int index, int[] path, int size, int k) {
if (index == arr.length) {
return lengthOfLIS(path, size) < k ? (arr.length - size) : Integer.MAX_VALUE;
} else {
int p1 = process1(arr, index + 1, path, size, k);
path[size] = arr[index];
int p2 = process1(arr, index + 1, path, size + 1, k);
return Math.min(p1, p2);
}
}
public static int lengthOfLIS(int[] arr, int size) {
if (size == 0) {
return 0;
}
int[] ends = new int[size];
ends[0] = arr[0];
int right = 0;
int l = 0;
int r = 0;
int m = 0;
int max = 1;
for (int i = 1; i < size; i++) {
l = 0;
r = right;
while (l <= r) {
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;
}
// arr[0...index-1]上,选择了一些数字,之前的决定!
// len长度了len = 3 1 2 3
// arr[index....]是能够决定的,之前的,已经不能再决定了
// 返回让最终保留的数字凑不足k长度的情况下至少要删几个
public static int zuo(int[] arr, int index, int len, int k) {
if (len == k) {
return Integer.MAX_VALUE;
}
// 凑的(1...len)还不到(1...k)
if (index == arr.length) {
return 0;
}
// 没凑到 < k, 有数字!
int cur = arr[index];
// 可能性1保留
// 可能性2删除
// 1...3 3
if (len >= cur || len + 1 < cur) {
return zuo(arr, index + 1, len, k);
}
// 1..3 4
// len + 1 == cur
// 可能性1保留
int p1 = zuo(arr, index + 1, len + 1, k);
// 可能性2删除
int p2 = Integer.MAX_VALUE;
int next2 = zuo(arr, index + 1, len, k);
if(next2 != Integer.MAX_VALUE) {
p2 = 1 + next2;
}
return Math.min(p1, p2);
}
// 正式方法
// 时间复杂度O(N*K)
public static int minRemove2(int[] arr, int k) {
int n = arr.length;
int[][] dp = new int[n][k];
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
dp[i][j] = -1;
}
}
return process2(arr, k, 0, 0, dp);
}
public static int process2(int[] arr, int k, int index, int range, int[][] dp) {
if (range == k) {
return Integer.MAX_VALUE;
}
if (index == arr.length) {
return 0;
}
if (dp[index][range] != -1) {
return dp[index][range];
}
int ans = 0;
if (arr[index] == range + 1) {
int p1 = process2(arr, k, index + 1, range, dp);
p1 += p1 != Integer.MAX_VALUE ? 1 : 0;
int p2 = process2(arr, k, index + 1, range + 1, dp);
ans = Math.min(p1, p2);
} else {
ans = process2(arr, k, index + 1, range, dp);
}
dp[index][range] = ans;
return ans;
}
// 为了验证
public static int[] randomArray(int len, int k) {
int[] arr = new int[len];
for (int i = 0; i < len; i++) {
arr[i] = (int) (Math.random() * k) + 1;
}
return arr;
}
// 为了验证
public static void main(String[] args) {
int N = 15;
int K = 6;
int testTime = 10000;
System.out.println("测试开始");
for (int i = 0; i < testTime; i++) {
int len = (int) (Math.random() * N) + 1;
int k = (int) (Math.random() * K) + 1;
int[] arr = randomArray(len, k);
int ans1 = minRemove1(arr, k);
int ans2 = minRemove2(arr, k);
if (ans1 != ans2) {
System.out.println("出错了!");
for (int num : arr) {
System.out.print(num + " ");
}
System.out.println();
System.out.println("k : " + k);
System.out.println("ans1 : " + ans1);
System.out.println("ans2 : " + ans2);
break;
}
}
System.out.println("测试结束");
}
}