给定一个正整数N ,任务是计算连续数字之间具有非递增顺序绝对差的N位数字的数量。
例子:
Input: N = 1
Output: 10
Explanation:
All numbers from 0 to 9 satisfy the given condition as there is only one digit.
Input: N = 3
Output: 495
朴素方法:解决给定问题的最简单方法是迭代所有可能的 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 )