📌  相关文章
📜  计算包含每个可能数字的 N 位数字至少一次

📅  最后修改于: 2021-09-17 07:07:04             🧑  作者: Mango

给定一个正整数N,任务是计算N位数字的数量,使得[0-9]中的每个数字至少出现一次。

例子 :

朴素方法:解决问题的最简单方法是生成所有可能的N位数字,对于每个这样的数字,检查其所有数字是否满足要求的条件。
时间复杂度: O(10 N *N)
辅助空间: O(1)

高效方法:为了优化上述方法,想法是使用动态规划,因为它具有重叠的子问题和最优子结构。子问题可以使用记忆存储在dp[][] 表中,其中dp[digit][mask]存储从第 th位到最后的答案,当包含的数字使用掩码表示时

请按照以下步骤解决此问题:

  • 定义一个递归函数,比如countOfNumbers(digit, mask) ,并执行以下步骤:
    • Base Case:如果digit的值等于N+1,则检查掩码的值是否等于(1 << 10 – 1)。如果发现为真,则返回1作为有效的N 位数字
    • 如果已经计算了状态dp[digit][mask]的结果,则返回此状态dp[digit][mask]
    • 如果当前位置为1 ,则可以放置[1-9] 中的任何数字。如果N等于1 ,则也可以放置0
    • 对于任何其他位置,可以放置[0-9] 中的任何数字。
    • 如果包含特定数字‘i’ ,则将掩码更新掩码 = 掩码 | (1<<我)。
    • 进行有效放置后,递归调用索引digit+1countOfNumbers函数
    • 返回所有可能的有效数字位置的总和作为答案。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Stores the dp-states
long long dp[100][1 << 10];
 
// Function to calculate the count of
// N-digit numbers that contains all
// digits from [0-9] atleast once
long long countOfNumbers(int digit,
                         int mask, int N)
{
    // If all digits are traversed
    if (digit == N + 1) {
 
        // Check if all digits are
        // included in the mask
        if (mask == (1 << 10) - 1)
            return 1;
        return 0;
    }
 
    long long& val = dp[digit][mask];
 
    // If the state has
    // already been computed
    if (val != -1)
        return val;
 
    val = 0;
 
    // If the current digit is 1, any
    // digit from [1-9] can be placed.
    // If N==1, 0 can also be placed
    if (digit == 1) {
        for (int i = (N == 1 ? 0 : 1); i <= 9; ++i) {
 
            val += countOfNumbers(digit + 1,
                                  mask | (1 << i), N);
        }
    }
 
    // For other positions, any digit
    // from [0-9] can be placed
    else {
        for (int i = 0; i <= 9; ++i) {
 
            val += countOfNumbers(digit + 1,
                                  mask | (1 << i), N);
        }
    }
 
    // Return the answer
    return val;
}
 
// Driver Code
int main()
{
    // Initializing dp array with -1.
    memset(dp, -1, sizeof dp);
 
    // Given Input
    int N = 10;
 
    // Function Call
    cout << countOfNumbers(1, 0, N);
 
    return 0;
}


Javascript


输出:
3265920

时间复杂度: O( N 2 *2 10 )
辅助空间: O( N*2 10 )