整型数组arr长度为n(3 <= n <= 10^4),最初每个数字是<=200的正数且满足如下条件:
- arr[0] <= arr[1]
2.arr[n-1] <= arr[n-2] - arr[i] <= max(arr[i-1], arr[i+1])
但是在arr有些数字丢失了,比如k位置的数字之前是正数,丢失之后k位置的数字为0。请你根据上述条件, 计算可能有多少种不同的arr可以满足以上条件。
比如 [6,0,9] 只有还原成 [6,9,9]满足全部三个条件,所以返回1种。
public class Main {
/**
* 0 和前一个数相等 * 1 比前一个数小 * 2 比前一个数大
*/
private static int solve1(int[] arr, int index, int smaller, int expect) {
if (index == arr.length - 1) {
return (smaller == 0 || smaller == 1) && (arr[index] == 0 || arr[index] == expect) ? 1 : 0;
}
if (arr[index] != 0 && arr[index] != expect) {
return 0;
}
int ret = 0;
if (smaller == 0 || smaller == 1) {
for (int i = 1; i <= 200; ++i) {
ret += solve1(arr, index + 1, i == expect ? 0 : (i < expect ? 1 : 2), i);
}
} else {
for (int i = expect; i <= 200; ++i) {
ret += solve1(arr, index + 1, i == expect ? 0 : 2, i);
}
}
return ret;
}
private static int solve2(int[] arr) {
int n = arr.length;
int[][] dp = new int[3][201];
int[][] helper;
for (int i = 1; i <= 200; ++i) {
dp[0][i] = (arr[n - 1] == 0 || arr[n - 1] == i) ? 1 : 0;
dp[1][i] = (arr[n - 1] == 0 || arr[n - 1] == i) ? 1 : 0;
}
int[][] preSum = new int[3][201];
for (int i = 1; i <= 200; ++i) {
preSum[0][i] = preSum[0][i - 1] + dp[0][i];
preSum[1][i] = preSum[1][i - 1] + dp[1][i];
}
for (int index = n - 2; index >= 0; --index) {
helper = new int[3][201];
for (int expect = 1; expect <= 200; ++expect) {
if ((arr[index] != 0 && arr[index] != expect)) {
continue;
}
for (int smaller = 0; smaller <= 2; ++smaller) {
int ret = 0;
if (smaller == 0 || smaller == 1) {
ret += getRegionSum(preSum[1], 1, expect - 1);
ret += dp[0][expect];
ret += getRegionSum(preSum[2], expect + 1, 200);
} else {
ret += dp[0][expect];
ret += getRegionSum(preSum[2], expect + 1, 200);
}
helper[smaller][expect] = ret;
}
}
dp = helper;
for (int expect = 1; expect <= 200; ++expect) {
preSum[0][expect] = preSum[0][expect - 1] + dp[0][expect];
preSum[1][expect] = preSum[1][expect - 1] + dp[1][expect];
preSum[2][expect] = preSum[2][expect - 1] + dp[2][expect];
}
}
int ret = 0;
if (arr[0] == 0) {
for (int i = 1; i <= 200; ++i) {
ret += dp[2][i];
}
} else {
ret += dp[2][arr[0]];
}
return ret;
}
private static int getRegionSum(int[] preSum, int start, int end) {
if (start > end) {
return 0;
}
if (start == 0) {
return preSum[end];
}
return preSum[end] - preSum[start - 1];
}
public static int ways1(int[] arr) {
if (arr == null || arr.length == 0) {
return 0;
}
if (arr.length == 1) {
return arr[0] == 0 ? 200 : 1;
}
int ret = 0;
if (arr[0] == 0) {
for (int i = 1; i <= 200; ++i) {
ret += solve1(arr, 0, 2, i);
}
} else {
ret += solve1(arr, 0, 2, arr[0]);
}
return ret;
}
public static int ways2(int[] arr) {
if (arr == null || arr.length == 0) {
return 0;
}
if (arr.length == 1) {
return arr[0] == 0 ? 200 : 1;
}
return solve2(arr);
}
}