JAVA || Digit DP
Complexity\n- Time complexity: O(num.length() * 2 * 2^10)\n Add your time complexity here, e.g. O(n) \n\n- Space complexity: O(num.length() * 2 * 2^10)\n Add yo
# Complexity\n- Time complexity: O(num.length() * 2 * 2^10)\n<!-- Add your time complexity here, e.g. $$O(n)$$ -->\n\n- Space complexity: O(num.length() * 2 * 2^10)\n<!-- Add your space complexity here, e.g. $$O(n)$$ -->\n\n# Code\n```\nclass Solution {\n    public int numDupDigitsAtMostN(int n) {\n        String num  = Integer.toString(n);\n        int[][][] dp = new int[num.length()][2][1 << 10];\n        for (int[][] a : dp) {\n            for (int[] b : a) Arrays.fill(b, -1);\n        }\n        return n - findNoDup(num, num.length(), 0, 0, 0, dp);\n    }\n\n    private int findNoDup(String num, int n, int index, int decider, int mask, int[][][] dp) {\n        if (index == n) return mask == 0 ? 0 : 1;\n        if (dp[index][decider][mask] != -1) return dp[index][decider][mask];\n        int res = 0;\n        int limit = decider == 1 ? 9 : num.charAt(index) - \'0\';\n\n        for (int i = 0; i <= limit; i++) {\n            if ((mask & (1 << i)) != 0) continue;\n            int newDecider = i < limit ? 1 : decider;\n            int newMask = i == 0 && mask == 0 ? mask : mask | (1 << i);\n            res += findNoDup(num, n, index + 1, newDecider, newMask, dp);\n        }\n\n        return dp[index][decider][mask] = res;\n    }\n}\n```
['Dynamic Programming', 'Memoization', 'Java']