Numbers With Repeated Digits - Digit DP [JS]
- Get link
- X
- Other Apps
By
Anna An
on
Solution: Digit DP
Memoize each dp(i, mask, state, hasRepeat), where
i = the ith digitmask = bitmask which indicates which digit we have already usedstate = indicates whether the current number is tracking smaller, equal, or greater than n0 = smaller1 = equal2 = greater
hasRepeat = whether we have a repeated digit
If hasRepeat is true (1), count it as 1 way.
For each state, count the total number of ways after appending each digit (0 - 9).
state:
- If
digit < n[index], update state to0(smaller) if state is currently1(equal). - If
digit === n[index], keep state the same. - If
digit > n[index], update state to2(greater) if state is currently1(equal).
d = number of digits in n
Time Complexity: O(d * 2^10 * 3 * 2 * 10) 488msd * 2^10 * 3 * 2 = the number of different states we can have10 = at each state we have 10 options for digits 0-9
Space Complexity: O(d * 2^10 * 3 * 2) 62MB
var numDupDigitsAtMostN = function(n) {
let str = n.toString(), size = str.length, memo = new Map();
return dp(0, 0, 1, 0);
function dp(i, mask, state, hasRepeat) {
if (i === size) return state < 2 && hasRepeat ? 1 : 0;
let key = `${i},${mask},${state},${hasRepeat}`;
if (memo.has(key)) return memo.get(key);
let ans = hasRepeat;
for (let digit = 0; digit <= 9; digit++) {
if (i === 0 && digit === 0) continue;
let newMask = mask | (1 << digit), repeat = hasRepeat || (mask === newMask ? 1 : 0);
if (digit < Number(str[i])) {
ans += dp(i + 1, newMask, state === 1 ? 0 : state, repeat);
} else if (digit === Number(str[i])) {
ans += dp(i + 1, newMask, state, repeat);
} else {
ans += dp(i + 1, newMask, state === 1 ? 2 : state, repeat);
}
}
memo.set(key, ans);
return ans;
}
};
javascript
- Get link
- X
- Other Apps
Comments
Post a Comment