恢复数组的方法数

整型数组arr长度为n(3 <= n <= 10^4),最初每个数字是<=200的正数且满足如下条件:

  1. arr[0] <= arr[1]
    2.arr[n-1] <= arr[n-2]
  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);
    }
}
上一篇:凤凰OS


下一篇:Linux项目准备工作