📜  将每个数字作为其相邻数字的平均值的 N 位数字的计数

📅  最后修改于: 2021-09-22 10:01:18             🧑  作者: Mango

给定一个正整数N ,任务是计算N位数字的数量,其中数字中的每个数字是其相邻两位数字的平均值。

例子 :

朴素方法:解决给定问题的最简单方法是迭代所有可能的 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 现场工作专业课程学生竞争性编程现场课程