给定一个正整数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 = 2
Output: 90
朴素方法:解决给定问题的最简单方法是迭代所有可能的 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] 中的任何数字。
- 否则,考虑三个数字prev1,prev2,而目前的数字要放在它尚未决定。在这三个数字,prev1必须是平均prev2和当前数字的。因此,当前数字 = (2*prev1) – prev2。如果current >= 0并且current <= 9那么我们可以将它放在给定的位置。否则返回0。
- 由于均值涉及整数除法,如果(current + 1) >= 0且(current + 1) ≤ 9 ,则(current + 1)也可以放在当前位置。
- 进行有效放置后,递归调用索引(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 find number of 'N'
// digit numbers such that the element
// is mean of sum of its adjacent digits
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 current position is 1,
// then any digit from [1-9]
// can be placed.
// If n = 1, 0 can be also placed.
if (digit == 1) {
for (int i = (n == 1 ? 0 : 1); i <= 9; ++i) {
val += countOfNumbers(
digit + 1, i, prev1, n);
}
}
// If current position is 2,
// then any digit from [1-9]
// can be placed.
else if (digit == 2) {
for (int i = 0; i <= 9; ++i) {
val += countOfNumbers(
digit + 1, i, prev1, n);
}
}
else {
// previous digit selected is the mean.
int mean = prev1;
// mean = (current + prev2) / 2
// current = (2 * mean) - prev2
int current = (2 * mean) - prev2;
// Check if current and current+1
// can be valid placements
if (current >= 0 and current <= 9)
val += countOfNumbers(digit + 1, current, prev1,
n);
if ((current + 1) >= 0 and (current + 1) <= 9)
val += countOfNumbers(digit + 1, current + 1,
prev1, n);
}
// return answer
return val;
}
// Driver code
int main()
{
// Initializing dp array with -1.
memset(dp, -1, sizeof dp);
// Given Input
int n = 2;
// Function call
cout << countOfNumbers(1, 0, 0, n) << endl;
return 0;
}
Java
// Java program for the above approach
import java.util.*;
class GFG{
static int dp[][][] = new int[100][10][10];
// Function to find number of 'N'
// digit numbers such that the element
// is mean of sum of its adjacent digits
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 current position is 1,
// then any digit from [1-9]
// can be placed.
// If n = 1, 0 can be also placed.
if (digit == 1) {
for (int i = (n == 1 ? 0 : 1); i <= 9; ++i) {
val += countOfNumbers(
digit + 1, i, prev1, n);
}
}
// If current position is 2,
// then any digit from [1-9]
// can be placed.
else if (digit == 2) {
for (int i = 0; i <= 9; ++i) {
val += countOfNumbers(
digit + 1, i, prev1, n);
}
}
else {
// previous digit selected is the mean.
int mean = prev1;
// mean = (current + prev2) / 2
// current = (2 * mean) - prev2
int current = (2 * mean) - prev2;
// Check if current and current+1
// can be valid placements
if (current >= 0 && current <= 9)
val += countOfNumbers(digit + 1, current, prev1,
n);
if ((current + 1) >= 0 && (current + 1) <= 9)
val += countOfNumbers(digit + 1, current + 1,
prev1, n);
}
// return answer
return val;
}
// Driver code
public static void main(String[] args)
{
// Initializing dp array 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;
}
}
}
// Given Input
int n = 2;
// Function call
System.out.println(countOfNumbers(1, 0, 0, n));
}
}
// This code is contributed by sanjoy_62.
Python3
# python program for the above approach
dp = [[[-1 for i in range(10)] for col in range(20)] for row in range(100)]
# Function to find number of 'N'
# digit numbers such that the element
# is mean of sum of its adjacent digits
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 current position is 1,
# then any digit from [1-9]
# can be placed.
# If n = 1, 0 can be also placed.
if (digit == 1):
start = 1
if(n == 1):
start = 0
for i in range(start, 10):
val += countOfNumbers(digit + 1, i, prev1, n)
# If current position is 2,
# then any digit from [1-9]
# can be placed.
elif (digit == 2):
for i in range(0, 10):
val += countOfNumbers(digit + 1, i, prev1, n)
else:
# previous digit selected is the mean.
mean = prev1
# // mean = (current + prev2) / 2
# // current = (2 * mean) - prev2
current = (2 * mean) - prev2
# Check if current and current+1
# can be valid placements
if (current >= 0 and current <= 9):
val += countOfNumbers(digit + 1, current, prev1, n)
if ((current + 1) >= 0 and (current + 1) <= 9):
val += countOfNumbers(digit + 1, current + 1, prev1, n)
# return answer
return val
# Driver code
# Initializing dp array with -1.
# Given Input
n = 2
# Function call
print(countOfNumbers(1, 0, 0, n))
#cThis 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 find number of 'N'
// digit numbers such that the element
// is mean of sum of its adjacent digits
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 current position is 1,
// then any digit from [1-9]
// can be placed.
// If n = 1, 0 can be also placed.
if (digit == 1) {
for (int i = (n == 1 ? 0 : 1); i <= 9; ++i) {
val += countOfNumbers(
digit + 1, i, prev1, n);
}
}
// If current position is 2,
// then any digit from [1-9]
// can be placed.
else if (digit == 2) {
for (int i = 0; i <= 9; ++i) {
val += countOfNumbers(
digit + 1, i, prev1, n);
}
}
else {
// previous digit selected is the mean.
int mean = prev1;
// mean = (current + prev2) / 2
// current = (2 * mean) - prev2
int current = (2 * mean) - prev2;
// Check if current and current+1
// can be valid placements
if (current >= 0 && current <= 9)
val += countOfNumbers(digit + 1, current, prev1,
n);
if ((current + 1) >= 0 && (current + 1) <= 9)
val += countOfNumbers(digit + 1, current + 1,
prev1, n);
}
// return answer
return val;
}
// Driver Code
static public void Main ()
{
// Initializing dp array 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;
}
}
}
// Given Input
int n = 2;
// Function call
Console.Write(countOfNumbers(1, 0, 0, n));
}
}
// This code is contributed by code_hunt.
90
时间复杂度: O(N × 10 2 )
辅助空间: O(N × 10 2 )
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。