📌  相关文章
📜  相邻数字之间的绝对差不增加的N位数字的计数

📅  最后修改于: 2021-09-22 10:00:54             🧑  作者: Mango

给定一个正整数N ,任务是计算连续数字之间具有非递增顺序绝对差的N位数字的数量。

例子:

朴素方法:解决给定问题的最简单方法是迭代所有可能的 N 位数字,并计算那些数字为非递增顺序的数字。检查完所有数字后,打印count的值作为结果。

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

高效方法:上述方法也可以使用动态规划进行优化,因为上述问题具有重叠子问题和最优子结构。 The subproblems can be stored in dp[][][] table using memoization where dp[digit][prev1][prev2] stores the answer from the digit th position till the end, when the previous digit selected, is prev1 and the second选择的前一个数字是prev2 。请按照以下步骤解决问题:

  • 通过执行以下步骤定义递归函数,例如countOfNumbers(digit, prev1, prev2)
    • 如果digit的值等于N + 1,则在形成有效的N 位数字时返回1
    • 如果状态结果DP [数字] [prev1] [prev2]已经计算,返回此状态DP [数字] [prev1] [prev2。
    • 如果当前数字1 ,则可以放置[1, 9] 中的任何数字。如果N = 1 ,则也可以放置0
    • 如果当前数字2 ,则可以放置[0, 9] 中的任何数字。
    • 否则迭代从i = 0 到 i = 9 的所有数字,并检查条件(abs(prev1 – i) <= abs(prev1 – prev2) ) 是否有效,并相应地将满足‘i’值放在当前位置。
    • 进行有效放置后,递归调用索引(digit + 1)countOfNumbers函数。
    • 返回所有可能的有效数字位置的总和作为答案。
  • 打印函数countOfNumbers(1, 0, 0, N)返回的值作为结果。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
int dp[100][10][10];
 
// Function to count N-digit numbers
// having absolute difference between
// adjacent digits in non-increasing order
int countOfNumbers(int digit, int prev1,
                   int prev2, int n)
{
    // If digit = n + 1, a valid
    // n-digit number has been formed
    if (digit == n + 1) {
        return 1;
    }
 
    // If the state has
    // already been computed
    int& val = dp[digit][prev1][prev2];
 
    if (val != -1) {
        return val;
    }
    val = 0;
 
    // If the current digit is 1,
    // then any digit from [1-9]
    // can be placed
    if (digit == 1) {
 
        for (int i = (n == 1 ? 0 : 1);
             i <= 9; ++i) {
            val += countOfNumbers(
                digit + 1, i, prev1, n);
        }
    }
 
    // If the current digit is 2, any
    // digit from [0-9] can be placed
    else if (digit == 2) {
 
        for (int i = 0; i <= 9; ++i) {
 
            val += countOfNumbers(
                digit + 1, i, prev1, n);
        }
    }
 
    // For other digits, any digit i
    // can be placed which satisfies
    // abs(prev1 - i) <= abs(prev1 - prev2)
    else {
        int diff = abs(prev2 - prev1);
 
        for (int i = 0; i <= 9; ++i) {
 
            // If absolute difference is
            // less than or equal to diff
            if (abs(prev1 - i) <= diff) {
 
                val += countOfNumbers(
                    digit + 1, i,
                    prev1, n);
            }
        }
    }
    return val;
}
 
// Function to count N-digit numbers with
// absolute difference between adjacent
// digits in non increasing order
int countNumbersUtil(int N)
{
    // Initialize dp table with -1
    memset(dp, -1, sizeof dp);
 
    // Function Call
    cout << countOfNumbers(1, 0, 0, N);
}
 
// Driver code
int main()
{
    int N = 3;
    countNumbersUtil(N);
 
    return 0;
}


Java
// Java program for the above approach
import java.io.*;
 
class GFG{
   
static int dp[][][] = new int[100][10][10];
 
// Function to count N-digit numbers
// having absolute difference between
// adjacent digits in non-increasing order
static int countOfNumbers(int digit, int prev1,
                          int prev2, int n)
{
     
    // If digit = n + 1, a valid
    // n-digit number has been formed
    if (digit == n + 1)
    {
        return 1;
    }
 
    // If the state has
    // already been computed
    int val = dp[digit][prev1][prev2];
 
    if (val != -1)
    {
        return val;
    }
    val = 0;
 
    // If the current digit is 1,
    // then any digit from [1-9]
    // can be placed
    if (digit == 1)
    {
        for(int i = (n == 1 ? 0 : 1);
                i <= 9; ++i)
        {
            val += countOfNumbers(
                digit + 1, i, prev1, n);
        }
    }
 
    // If the current digit is 2, any
    // digit from [0-9] can be placed
    else if (digit == 2)
    {
        for(int i = 0; i <= 9; ++i)
        {
            val += countOfNumbers(
                digit + 1, i, prev1, n);
        }
    }
 
    // For other digits, any digit i
    // can be placed which satisfies
    // abs(prev1 - i) <= abs(prev1 - prev2)
    else
    {
        int diff = Math.abs(prev2 - prev1);
 
        for(int i = 0; i <= 9; ++i)
        {
             
            // If absolute difference is
            // less than or equal to diff
            if (Math.abs(prev1 - i) <= diff)
            {
                val += countOfNumbers(
                    digit + 1, i,
                    prev1, n);
            }
        }
    }
    return val;
}
 
// Function to count N-digit numbers with
// absolute difference between adjacent
// digits in non increasing order
static void countNumbersUtil(int N)
{
     
    // Initialize dp table with -1
    for(int i = 0; i < 100; i++)
    {
        for(int j = 0; j < 10; j++)
        {
            for(int k = 0; k < 10; k++)
            {
                dp[i][j][k] = -1;
            }
        }
    }
     
    // Function Call
    System.out.println(countOfNumbers(1, 0, 0, N));
}
 
// Driver code
public static void main(String[] args)
{
    int N = 3;
     
    countNumbersUtil(N);
}
}
 
// This code is contributed by Dharanendra L V.


Python3
# Python3 program for the above approach
dp = [[[0 for i in range(10)]
          for col in range(10)]
          for row in range(100)]
 
# Function to count N-digit numbers
# having absolute difference between
# adjacent digits in non-increasing order
def countOfNumbers(digit, prev1, prev2, n):
     
    # If digit = n + 1, a valid
    # n-digit number has been formed
    if (digit == n + 1):
        return 1
 
    # If the state has
    # already been computed
    val = dp[digit][prev1][prev2]
 
    if (val != -1):
        return val
         
    val = 0
 
    # If the current digit is 1,
    # then any digit from [1-9]
    # can be placed
    if (digit == 1):
        i = 1
        if n == 1:
            i = 0
             
        for j in range(i, 10):
            val += countOfNumbers(digit + 1, j, prev1, n)
 
    # If the current digit is 2, any
    # digit from [0-9] can be placed
    elif (digit == 2):
        for i in range(0, 10):
            val += countOfNumbers(digit + 1, i, prev1, n)
 
    # For other digits, any digit i
    # can be placed which satisfies
    # abs(prev1 - i) <= abs(prev1 - prev2)
    else:
        diff = abs(prev2 - prev1)
        for i in range(0, 10):
             
            # If absolute difference is
            # less than or equal to diff
            if (abs(prev1 - i) <= diff):
                val += countOfNumbers(digit + 1, i, prev1, n)
    return val
 
# Function to count N-digit numbers with
# absolute difference between adjacent
# digits in non increasing order
def countNumbersUtil(N):
     
    # Initialize dp table with -1
    for i in range(0, 100):
        for j in range(0, 10):
            for k in range(0, 10):
                dp[i][j][k] = -1
 
    # Function Call
    print(countOfNumbers(1, 0, 0, N))
 
# Driver code
N = 3
 
countNumbersUtil(N)
 
# This code is contributed by amreshkumar3


C#
// C# program for the above approach
using System;
 
class GFG{
     
static int[,,] dp = new int[100, 10, 10];
 
// Function to count N-digit numbers
// having absolute difference between
// adjacent digits in non-increasing order
static int countOfNumbers(int digit, int prev1,
                          int prev2, int n)
{
     
    // If digit = n + 1, a valid
    // n-digit number has been formed
    if (digit == n + 1)
    {
        return 1;
    }
 
    // If the state has
    // already been computed
    int val = dp[digit, prev1, prev2];
 
    if (val != -1)
    {
        return val;
    }
    val = 0;
 
    // If the current digit is 1,
    // then any digit from [1-9]
    // can be placed
    if (digit == 1)
    {
        for(int i = (n == 1 ? 0 : 1);
                i <= 9; ++i)
        {
            val += countOfNumbers(
                digit + 1, i, prev1, n);
        }
    }
 
    // If the current digit is 2, any
    // digit from [0-9] can be placed
    else if (digit == 2)
    {
        for(int i = 0; i <= 9; ++i)
        {
            val += countOfNumbers(
                digit + 1, i, prev1, n);
        }
    }
 
    // For other digits, any digit i
    // can be placed which satisfies
    // abs(prev1 - i) <= abs(prev1 - prev2)
    else
    {
        int diff = Math.Abs(prev2 - prev1);
 
        for(int i = 0; i <= 9; ++i)
        {
             
            // If absolute difference is
            // less than or equal to diff
            if (Math.Abs(prev1 - i) <= diff)
            {
                val += countOfNumbers(
                    digit + 1, i,
                    prev1, n);
            }
        }
    }
    return val;
}
 
// Function to count N-digit numbers with
// absolute difference between adjacent
// digits in non increasing order
static void countNumbersUtil(int N)
{
     
    // Initialize dp table with -1
    for(int i = 0; i < 100; i++)
    {
        for(int j = 0; j < 10; j++)
        {
            for(int k = 0; k < 10; k++)
            {
                dp[i, j, k] = -1;
            }
        }
    }
     
    // Function Call
    Console.WriteLine(countOfNumbers(1, 0, 0, N));
}
 
// Driver code
static public void Main()
{
    int N = 3;
     
    countNumbersUtil(N);
}
}
 
// This code is contributed by splevel62


输出
495

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