package com.freetymekiyan.algorithms.level.medium; /** * Given a non-negative integer n, count all numbers with unique digits, x, where 0 ≤ x < 10^n. * <p> * Example: * Given n = 2, return 91. (The answer should be the total numbers in the range of 0 ≤ x < 100, excluding * [11,22,33,44,55,66,77,88,99]) * <p> * Hint: * <p> * A direct way is to use the backtracking approach. * Backtracking should contains three states which are (the current number, number of steps to get that number and a * bitmask which represent which number is marked as visited so far in the current number). Start with state (0,0,0) and * count all valid number till we reach number of steps equals to 10n. * This problem can also be solved using a dynamic programming approach and some knowledge of combinatorics. * Let f(k) = count of numbers with unique digits with length equals k. * f(1) = 10, ..., f(k) = 9 * 9 * 8 * ... (9 - k + 2) [The first factor is 9 because a number cannot start with 0]. * <p> * Tags: Dynamic Programming, Backtracking, Math */ public class CountingNumbersWithUniqueDigits { /** * DP. * Think about how to use combination to build a number with unique digits. * f(1) = 10, f(2) = 9 * 9, f(3) = 9 * 9 * 8, f(4) = 9 * 9 * 8 * 7 ... * f(k) = 9 * 9 * 8 * ... * (9 - k + 2), 2 <= k <= 10 * f(k) = f(10), k > 10 */ public int countNumbersWithUniqueDigits(int n) { if (n == 0) { return 1; } int res = 10; int uniqueDigits = 9; int availableNums = 9; while (n > 1 && availableNums > 0) { uniqueDigits *= availableNums; res += uniqueDigits; availableNums--; n--; } return res; } }