给定两个整数N和K ,任务是找到N 位数字的计数,使得数字中相邻数字的绝对差不大于K 。
例子:
Input: N = 2, K = 1
Output: 26
Explanation: The numbers are 10, 11, 12, 21, 22, 23, 32, 33, 34, 43, 44, 45, 54, 55, 56, 65, 66, 67, 76, 77, 78, 87, 88, 89, 98, 99
Input: N = 3, K = 2
Output: 188
天真的方法
最简单的方法是迭代所有N位数字并检查每个数字是否相邻数字的绝对差小于或等于 K。
时间复杂度: O(10 N * N)
有效的方法:
为了优化上述方法,我们需要使用动态规划方法和范围更新
- 初始化一个 DP[][] 数组,其中dp[i][j]存储具有i位数字并以j结尾的数字的计数。
- 将数组从2迭代到N并检查最后一位数字是否为 j,则此位置允许的数字在(max(0, jk), min(9, j+k)) 范围内。对该范围执行范围更新。
- 现在使用 Prefix Sum 来获得实际答案。
下面是上述方法的实现:
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)