1class Solution {2 private char[] bound;3 private int[] allowed;4 private Integer[][][] memo;5
6 public int atMostNGivenDigitSet(String[] digits, int n) {7 bound = Integer.toString(n).toCharArray();8 allowed = new int[digits.length];9 for (int i = 0; i < digits.length; i++) allowed[i] = digits[i].charAt(0) - '0';10 memo = new Integer[bound.length][2][2];11 return count(0, 1, 0);12 }13
14 private int count(int pos, int tight, int started) {15 if (pos == bound.length) return started;16 if (memo[pos][tight][started] != null) return memo[pos][tight][started];17 int limit = tight == 1 ? bound[pos] - '0' : 9;18 int total = started == 0 ? count(pos + 1, 0, 0) : 0;19 for (int digit : allowed) {20 if (digit > limit) break;21 int nextTight = tight == 1 && digit == limit ? 1 : 0;22 total += count(pos + 1, nextTight, 1);23 }24 memo[pos][tight][started] = total;25 return total;26 }27}