📜  N位数的计数,相邻位数的绝对差不超过K

📅  最后修改于: 2021-06-25 18:17:27             🧑  作者: Mango

给定两个整数NK ,任务是找到N位数字的计数,以使数字中相邻数字的绝对差不大于K。

例子:

天真的方法
最简单的方法是遍历所有N个数字,并检查每个数字,如果相邻数字的绝对差小于或等于K。
时间复杂度: O(10 N * N)

高效方法:
要优化上述方法,我们需要结合使用动态编程方法和范围更新

  • 初始化DP [] []数组,其中dp [i] [j]存储具有i个数字并以j结尾的数字的计数。
  • 将数组从2迭代到N,并检查最后一位是否为j,则该位置允许的位数在(max(0,jk),min(9,j + k))范围内。在此范围上执行范围更新。
  • 现在,使用“前缀总和”获取实际答案。

下面是上述方法的实现:

C++
// C++ implementation of
// the above approach
#include 
using namespace std;
 
// Function to return count
// of N-digit numbers with
// absolute difference of
// adjacent digits not
// exceeding K
long long getCount(int n, int k)
{
    // For 1-digit numbers,
    // the count is 10
    if (n == 1)
        return 10;
 
    long long dp[n + 1][11];
 
    // dp[i][j] stores the number
    // of such i-digit numbers
    // ending in j
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j < 11; j++)
            dp[i][j] = 0;
    }
    // Initialize count for
    // 1-digit numbers
    for (int i = 1; i <= 9; i++)
        dp[1][i] = 1;
 
    // Compute values for count of
    // digits greater than 1
    for (int i = 2; i <= n; i++) {
        for (int j = 0; j <= 9; j++) {
 
            // Find the range of allowed
            // numbers if last digit is j
            int l = max(0, j - k);
            int r = min(9, j + k);
 
            // Perform Range update
            dp[i][l] += dp[i - 1][j];
            dp[i][r + 1] -= dp[i - 1][j];
        }
 
        // Prefix sum to find actual
        // values of i-digit numbers
        // ending in j
        for (int j = 1; j <= 9; j++)
            dp[i][j] += dp[i][j - 1];
    }
 
    // Stores the final answer
    long long count = 0;
    for (int i = 0; i <= 9; i++)
        count += dp[n][i];
 
    return count;
}
 
// Driver Code
int main()
{
    int N = 2, K = 1;
    cout << getCount(N, K);
}


Java
// Java Program to implement
// the above approach
import java.util.*;
class GFG {
 
    // Function to return count of such numbers
    public static long getCount(int n, int k)
    {
        // For 1-digit numbers, the count
        // is 10 irrespective of K
        if (n == 1)
            return 10;
 
        // dp[i][j] stores the number
        // of such i-digit numbers
        // ending in j
        long dp[][]
            = new long[n + 1][11];
 
        // Initialize count for
        // 1-digit numbers
        for (int i = 1; i <= 9; i++)
            dp[1][i] = 1;
 
        // Compute values for count of
        // digits greater than 1
        for (int i = 2; i <= n; i++) {
            for (int j = 0; j <= 9; j++) {
 
                // Find the range of allowed
                // numbers if last digit is j
                int l = Math.max(0, j - k);
                int r = Math.min(9, j + k);
 
                // Perform Range update
                dp[i][l] += dp[i - 1][j];
                dp[i][r + 1] -= dp[i - 1][j];
            }
 
            // Prefix sum to find actual values
            // of i-digit numbers ending in j
            for (int j = 1; j <= 9; j++)
                dp[i][j] += dp[i][j - 1];
        }
 
        // Stores the final answer
        long count = 0;
        for (int i = 0; i <= 9; i++)
            count += dp[n][i];
        return count;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int n = 2, k = 1;
        System.out.println(getCount(n, k));
    }
}


Python3
# Python 3 Program to implement
# the above approach
 
# Function to return count
# of N-digit numbers with
# absolute difference of
# adjacent digits not
# exceeding K
def getCount(n, k):
 
    # For 1-digit numbers, the
    # count is 10
    if n == 1:
        return 10
     
    # dp[i][j] stores the count of
    # i-digit numbers ending with j       
    dp = [[0 for x in range(11)]
            for y in range(n + 1)];    
     
     
    # Initialize count for
    # 1-digit numbers
    for i in range(1, 10):
        dp[1][i]= 1
     
    # Compute values for count
    # of digits greater than 1
    for i in range(2, n + 1):
        for j in range(0, 10):
             
            # Find the range of allowed
            # numbers if last digit is j
            l = max(0, j - k)
            r = min(9, j + k)
                 
            # Perform Range update
            dp[i][l] = dp[i][l] + dp[i-1][j]
            dp[i][r + 1] = dp[i][r + 1] - dp[i-1][j]
             
        # Prefix sum to find count of
        # of i-digit numbers ending with j
        for j in range(1, 10):
            dp[i][j] = dp[i][j] + dp[i][j-1]
     
    # Stores the final answer
    count = 0
     
    for i in range(0, 10):
        count = count + dp[n][i]
    return count
 
# Driver Code
n, k = 2, 1
print(getCount(n, k))


C#
// C# Program to implement
// the above approach
using System;
class GFG {
 
    // Function to return the
    // count of N-digit numbers
    // with absolute difference of
    // adjacent digits not exceeding K
    static long getCount(int n, int k)
    {
        // For 1-digit numbers, the
        // count is 10
        if (n == 1)
            return 10;
 
        // dp[i][j] stores the count of
        // i-digit numbers ending with j
        long[, ] dp = new long[n + 1, 11];
 
        // Initialize count for
        // 1-digit numbers
        for (int i = 1; i <= 9; i++)
            dp[1, i] = 1;
 
        // Compute values for count of
        // digits greater than 1
        for (int i = 2; i <= n; i++) {
            for (int j = 0; j <= 9; j++) {
 
                // Find the range of allowed
                // numbers with last digit j
                int l = Math.Max(0, j - k);
                int r = Math.Min(9, j + k);
 
                // Perform Range update
                dp[i, l] += dp[i - 1, j];
                dp[i, r + 1] -= dp[i - 1, j];
            }
 
            // Prefix sum to count i-digit
            // numbers ending in j
            for (int j = 1; j <= 9; j++)
                dp[i, j] += dp[i, j - 1];
        }
 
        // Stores the final answer
        long count = 0;
        for (int i = 0; i <= 9; i++)
            count += dp[n, i];
        return count;
    }
 
    // Driver Code
    public static void Main()
    {
        int n = 2, k = 1;
        Console.WriteLine(getCount(n, k));
    }
}


Javascript


输出:
26

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