📌  相关文章
📜  严格递增 N 位数字的计数

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

给定一个正整数N ,任务是找到N 位数字的数量,使得每个数字都小于其相邻数字。

例子:

朴素方法:解决给定问题的最简单方法是迭代所有可能的N位数字,对于每个这样的数字,检查其所有数字是否满足给定标准。如果发现是真的,那么数一数这些数字。检查所有数字后,打印获得的总数。

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

高效方法:上述方法也可以通过使用动态规划进行优化,因为它具有重叠的子问题和最优子结构。 The subproblems can be stored in dp[][][] table using memoization where dp[i][prev][sign] stores the result from the i th position till the end, when the previous digit selected, is prev and the variable符号用于指示当前数字是否必须小于或大于前一个数字。请按照以下步骤解决问题:

  • 定义一个递归函数,例如, countOfNumbers(digit, prev, sign)具有三个参数:digit、sign 和 prev。
    • 检查基本情况,即,如果i的值等于N,则在形成有效的N位数字时返回1
    • 初始化一个变量,例如val = 0 ,以存储 N 位数字的所有可能计数。
    • 如果i0 ,则可以放置[1 – 9] 中的任何数字,如果N = 1 ,则也可以放置0
    • 如果i1 ,则可以放置[0 – 9] 中的任何数字,使得当前数字等于前一个数字。
    • 如果符号的值为1 ,则放置当前数字使其小于前一个数字并将符号更改为0以供下一次递归调用。
    • 如果符号的值是0,然后将当前数字,使得它比以前的数字更多,并更改标志1为下一个递归调用。
    • 进行有效放置后,递归调用索引(digit + 1)countOfNumbers函数。
    • 作为每个当前递归调用的结果,返回所有可能的有效数字位置的总和。
  • 完成上述步骤后,将函数countOfNumbers(0, N, 0, 0)返回的值打印为结果计数。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Declaration of dp table
int dp[100][10][2];
 
// Function to find the count of all N
// digit numbers such that all the digit
// is less than its adjacent digits
int solve(int i, int n, int prev, bool sign)
{
    // Base Case:
    // If i = n, then return 1 as valid
    // number has been formed
    if (i == n) {
        return 1;
    }
 
    int& val = dp[i][prev][sign];
 
    // If the state has already been
    // computed, then return it
    if (val != -1)
        return val;
 
    // Stores the total count of ways
    // for the current recursive call
    val = 0;
 
    // If i = 0, any digit from [1-9]
    // can  be placed and also if N = 1
    //, then 0 can also be placed
    if (i == 0) {
        for (int digit = (n == 1 ? 0 : 1);
             digit <= 9;
             ++digit) {
            val += solve(i + 1, n,
                         digit, sign);
        }
    }
 
    // If i = 1, any digit from [0-9]
    // can be placed such that digit
    // is not equal to previous digit
    else if (i == 1) {
        for (int digit = 0; digit <= 9;
             ++digit) {
 
            // If the current digit is
            // not same as the prev
            if (digit != prev) {
                val += solve(i + 1, n, digit,
                             (digit > prev));
            }
        }
    }
 
    else {
 
        // Place the current digit such
        // that it is less than the
        // previous digit
        if (sign == 1) {
            for (int digit = prev - 1;
                 digit >= 0;
                 --digit) {
 
                val += solve(i + 1, n,
                             digit, 0);
            }
        }
 
        // Place current digit such
        // that it is more than the
        // previous digit
        else {
            for (int digit = prev + 1;
                 digit <= 9;
                 ++digit) {
 
                val += solve(i + 1, n,
                             digit, 1);
            }
        }
    }
 
    // Return the resultant total count
    return val;
}
 
// Function to find all N-digit numbers
// satisfying the given criteria
void countNdigitNumber(int N)
{
 
    // Initialize an array dp[] with
    // all elements as -1
    memset(dp, -1, sizeof dp);
 
    // Function call to count all
    // possible ways
    cout << solve(0, N, 0, 0);
}
 
// Driver Code
int main()
{
    int N = 3;
    countNdigitNumber(N);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
public class MyClass
{
 
// Declaration of dp table
static int[][][] dp = new int[100][10][2];
 
// Function to find the count of all N
// digit numbers such that all the digit
// is less than its adjacent digits
static int solve(int i, int n, int prev, int sign)
{
   
    // Base Case:
    // If i = n, then return 1 as valid
    // number has been formed
    if (i == n) {
        return 1;
    }
 
    int val = dp[i][prev][sign];
 
    // If the state has already been
    // computed, then return it
    if (val != -1)
        return val;
 
    // Stores the total count of ways
    // for the current recursive call
    val = 0;
 
    // If i = 0, any digit from [1-9]
    // can  be placed and also if N = 1
    //, then 0 can also be placed
    if (i == 0) {
        for (int digit = (n == 1 ? 0 : 1);
             digit <= 9;
             ++digit) {
            val += solve(i + 1, n,
                         digit, sign);
        }
    }
 
    // If i = 1, any digit from [0-9]
    // can be placed such that digit
    // is not equal to previous digit
    else if (i == 1) {
        for (int digit = 0; digit <= 9;
             ++digit) {
 
            // If the current digit is
            // not same as the prev
            if (digit != prev) {
                val += solve(i + 1, n, digit,((digit > prev)?1:0));
            }
        }
    }
 
    else {
 
        // Place the current digit such
        // that it is less than the
        // previous digit
        if (sign == 1) {
            for (int digit = prev - 1;
                 digit >= 0;
                 --digit) {
 
                val += solve(i + 1, n,
                             digit, 0);
            }
        }
 
        // Place current digit such
        // that it is more than the
        // previous digit
        else {
            for (int digit = prev + 1;
                 digit <= 9;
                 ++digit) {
 
                val += solve(i + 1, n,
                             digit, 1);
            }
        }
    }
 
    // Return the resultant total count
    return val;
}
 
// Function to find all N-digit numbers
// satisfying the given criteria
static void countNdigitNumber(int N)
{
 
    // Initialize an array dp[] with
    // all elements as -1
    for (int[][] row : dp)
    {
        for (int[] rowColumn : row)
        {
            Arrays.fill(rowColumn, -1);
        }
    }
    // Function call to count all
    // possible ways
     System.out.println(solve(0, N, 0, 0));
}
 
// Driver Code
 public static void main(String args[])
{
    int N = 3;
    countNdigitNumber(N);
}
}
 
// This code is contributed by SoumikMondal


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
public class MyClass
{
 
// Declaration of dp table
static int[,,] dp = new int[100,10,2];
 
// Function to find the count of all N
// digit numbers such that all the digit
// is less than its adjacent digits
static int solve(int i, int n, int prev, int sign)
{
   
    // Base Case:
    // If i = n, then return 1 as valid
    // number has been formed
    if (i == n) {
        return 1;
    }
 
    int val = dp[i,prev,sign];
 
    // If the state has already been
    // computed, then return it
    if (val != -1)
        return val;
 
    // Stores the total count of ways
    // for the current recursive call
    val = 0;
 
    // If i = 0, any digit from [1-9]
    // can  be placed and also if N = 1
    //, then 0 can also be placed
    if (i == 0) {
        for (int digit = (n == 1 ? 0 : 1);
             digit <= 9;
             ++digit) {
            val += solve(i + 1, n,
                         digit, sign);
        }
    }
 
    // If i = 1, any digit from [0-9]
    // can be placed such that digit
    // is not equal to previous digit
    else if (i == 1) {
        for (int digit = 0; digit <= 9;
             ++digit) {
 
            // If the current digit is
            // not same as the prev
            if (digit != prev) {
                val += solve(i + 1, n, digit,((digit > prev)?1:0));
            }
        }
    }
 
    else {
 
        // Place the current digit such
        // that it is less than the
        // previous digit
        if (sign == 1) {
            for (int digit = prev - 1;
                 digit >= 0;
                 --digit) {
 
                val += solve(i + 1, n,
                             digit, 0);
            }
        }
 
        // Place current digit such
        // that it is more than the
        // previous digit
        else {
            for (int digit = prev + 1;
                 digit <= 9;
                 ++digit) {
 
                val += solve(i + 1, n,
                             digit, 1);
            }
        }
    }
 
    // Return the resultant total count
    return val;
}
 
// Function to find all N-digit numbers
// satisfying the given criteria
static void countNdigitNumber(int N)
{
 
    // Initialize an array []dp with
    // all elements as -1
    for(int i = 0;i<100;i++)
{
    for (int j = 0; j < 10; j++) {
        for (int k = 0; k < 2; k++)
            dp[i,j,k] = -1;
    }
}
    // Function call to count all
    // possible ways
     Console.WriteLine(solve(0, N, 0, 0));
}
 
// Driver Code
 public static void Main(String []args)
{
    int N = 3;
    countNdigitNumber(N);
}
}
 
// This code is contributed by 29AjayKumar


输出:
525

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

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程