Input: n =135Output: 110Explanation: There are 110 integers from 1 to 135 that are special.Some of the integers that are not special are:22,114, and 131.
A number is special if all its digits are unique. We can use digit dynamic programming (DP) to count numbers with unique digits up to n, by processing each digit position, tracking which digits have been used (with a bitmask), and whether we are still tight to the upper bound.
classSolution {
publicintcountSpecialNumbers(int n) {
String s = Integer.toString(n);
int len = s.length();
Integer[][][] dp =new Integer[len+1][1<<10][2];
return dfs(0, 0, true, false, s, dp);
}
privateintdfs(int pos, int mask, boolean tight, boolean leadingZero, String s, Integer[][][] dp) {
if (pos == s.length()) return leadingZero ? 0 : 1;
if (dp[pos][mask][tight ? 1 : 0]!=null) return dp[pos][mask][tight ? 1 : 0];
int res = 0, up = tight ? s.charAt(pos) -'0' : 9;
for (int d = 0; d <= up; d++) {
if ((mask == 0 && d == 0)) {
res += dfs(pos+1, mask, tight && d == up, true, s, dp);
} elseif ((mask & (1 << d)) == 0) {
res += dfs(pos+1, mask | (1 << d), tight && d == up, false, s, dp);
}
}
return dp[pos][mask][tight ? 1 : 0]= res;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
classSolution:
defcountSpecialNumbers(self, n: int) -> int:
s = str(n)
from functools import lru_cache
@lru_cache(None)
defdp(pos: int, mask: int, tight: bool, leading_zero: bool) -> int:
if pos == len(s):
return0if leading_zero else1 res =0 up = int(s[pos]) if tight else9for d in range(0, up+1):
if mask ==0and d ==0:
res += dp(pos+1, mask, tight and d == up, True)
elifnot (mask & (1<< d)):
res += dp(pos+1, mask | (1<< d), tight and d == up, False)
return res
return dp(0, 0, True, True)