给定两个整数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
朴素法和动态规划法:最简单的解法和需要 O(N) 辅助空间的动态规划法,请参考相邻数字绝对差不超过 K 的 N 位数字的计数。
节省空间的方法:
按照以下步骤优化上述方法:
- 在上述方法中,二维数组dp[][]被初始化,其中dp[i][j]存储具有i位数字并以j结尾的数字的计数。
- 可以观察到,任何长度i的答案仅取决于为i – 1生成的计数。因此,不是二维数组,而是初始化所有可能数字大小的数组 dp[] ,并且对于每个i到N , dp[j]存储长度i以数字j结尾的此类数字的计数。
- 初始化另一个数组next[]的所有可能数字的大小。
- 由于以值j结尾的个位数的计数始终为1 ,因此最初在所有索引处用1填充dp[] 。
- 迭代范围[2, N] ,对于范围i中的每个值,检查最后一位数字是否为j ,然后该位置允许的数字在范围(max(0, jk), min(9, j+k)) 。执行范围更新:
next[l] = next[l] + dp[j]
next[r + 1] = next[r + 1] – dp[j]
where l and r are max(0, j – k) and min(9, j + k) respectively.
- 对于特定的i值完成上述步骤后,计算next[] 的前缀和并使用next[]的值更新dp [] 。
下面是上述方法的实现:
C
// C program to implement the above approach
#include
// Function to find maximum between two numbers
int max(int num1, int num2)
{
return (num1 > num2 ) ? num1 : num2;
}
// Function to find minimum between two numbers
int min(int num1, int num2)
{
return (num1 > num2 ) ? num2 : num1;
}
// Function to return the count
// of such numbers
int getCount(int n, int k)
{
// For 1-digit numbers, the count
// is 10 irrespective of K
if (n == 1)
return 10;
// dp[j] stores the number
// of such i-digit numbers
// ending with j
int dp[11] = {0};
// Stores the results of length i
int next[11] = {0};
// Initialize count for
// 1-digit numbers
for(int i = 1; i <= 9; i++)
dp[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
next[l] += dp[j];
next[r + 1] -= dp[j];
}
// Prefix sum to find actual count
// of i-digit numbers ending with j
for(int j = 1; j <= 9; j++)
next[j] += next[j - 1];
// Update dp[]
for(int j = 0; j < 10; j++)
{
dp[j] = next[j];
next[j] = 0;
}
}
// Stores the final answer
int count = 0;
for(int i = 0; i <= 9; i++)
count += dp[i];
// Return the final answer
return count;
}
// Driver Code
int main()
{
int n = 2, k = 1;
printf("%d", getCount(n, k));
}
// This code is contributed by piyush3010.
C++
// C++ Program to implement
// the above approach
#include
using namespace std;
// Function to find maximum between two numbers
int max(int num1, int num2)
{
return (num1 > num2 ) ? num1 : num2;
}
// Function to find minimum between two numbers
int min(int num1, int num2)
{
return (num1 > num2 ) ? num2 : num1;
}
// Function to return the count
// of such numbers
int getCount(int n, int k)
{
// For 1-digit numbers, the count
// is 10 irrespective of K
if (n == 1)
return 10;
// dp[j] stores the number
// of such i-digit numbers
// ending with j
int dp[11] = {0};
// Stores the results of length i
int next[11] = {0};
// Initialize count for
// 1-digit numbers
for(int i = 1; i <= 9; i++)
dp[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
next[l] += dp[j];
next[r + 1] -= dp[j];
}
// Prefix sum to find actual count
// of i-digit numbers ending with j
for(int j = 1; j <= 9; j++)
next[j] += next[j - 1];
// Update dp[]
for(int j = 0; j < 10; j++)
{
dp[j] = next[j];
next[j] = 0;
}
}
// Stores the final answer
int count = 0;
for(int i = 0; i <= 9; i++)
count += dp[i];
// Return the final answer
return count;
}
// Driver Code
int main()
{
int n = 2, k = 1;
cout << getCount(n, k);
return 0;
}
Java
// Java Program to implement
// the above approach
import java.util.*;
class GFG {
// Function to return the 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[j] stores the number
// of such i-digit numbers
// ending with j
long dp[] = new long[11];
// Stores the results of length i
long next[] = new long[11];
// Initialize count for
// 1-digit numbers
for (int i = 1; i <= 9; i++)
dp[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
next[l] += dp[j];
next[r + 1] -= dp[j];
}
// Prefix sum to find actual count
// of i-digit numbers ending with j
for (int j = 1; j <= 9; j++)
next[j] += next[j - 1];
// Update dp[]
for (int j = 0; j < 10; j++) {
dp[j] = next[j];
next[j] = 0;
}
}
// Stores the final answer
long count = 0;
for (int i = 0; i <= 9; i++)
count += dp[i];
// Return the final answer
return count;
}
// Driver Code
public static void main(String[] args)
{
int n = 2, k = 1;
System.out.println(getCount(n, k));
}
}
Python3
# Python3 program to implement
# the above approach
# Function to return the count
# of such numbers
def getCount(n, K):
# For 1-digit numbers, the count
# is 10 irrespective of K
if(n == 1):
return 10
# dp[j] stores the number
# of such i-digit numbers
# ending with j
dp = [0] * 11
# Stores the results of length i
next = [0] * 11
# Initialize count for
# 1-digit numbers
for i in range(1, 9 + 1):
dp[i] = 1
# Compute values for count of
# digits greater than 1
for i in range(2, n + 1):
for j in range(9 + 1):
# Find the range of allowed
# numbers if last digit is j
l = max(0, j - k)
r = min(9, j + k)
# Perform Range update
next[l] += dp[j]
next[r + 1] -= dp[j]
# Prefix sum to find actual count
# of i-digit numbers ending with j
for j in range(1, 9 + 1):
next[j] += next[j - 1]
# Update dp[]
for j in range(10):
dp[j] = next[j]
next[j] = 0
# Stores the final answer
count = 0
for i in range(9 + 1):
count += dp[i]
# Return the final answer
return count
# Driver code
if __name__ == '__main__':
n = 2
k = 1
print(getCount(n, k))
# This code is contributed by Shivam Singh
C#
// C# program to implement
// the above approach
using System;
class GFG{
// Function to return the 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[j] stores the number
// of such i-digit numbers
// ending with j
long []dp = new long[11];
// Stores the results of length i
long []next = new long[11];
// Initialize count for
// 1-digit numbers
for(int i = 1; i <= 9; i++)
dp[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
next[l] += dp[j];
next[r + 1] -= dp[j];
}
// Prefix sum to find actual count
// of i-digit numbers ending with j
for(int j = 1; j <= 9; j++)
next[j] += next[j - 1];
// Update []dp
for(int j = 0; j < 10; j++)
{
dp[j] = next[j];
next[j] = 0;
}
}
// Stores the readonly answer
long count = 0;
for(int i = 0; i <= 9; i++)
count += dp[i];
// Return the readonly answer
return count;
}
// Driver Code
public static void Main(String[] args)
{
int n = 2, k = 1;
Console.WriteLine(getCount(n, k));
}
}
// This code is contributed by amal kumar choubey
Javascript
输出:
26
时间复杂度: O(N)
辅助空间: O(1)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。