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

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_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("测试结束");
}
}