给定一个正整数N ,任务是找到N 位数字的数量,使得每个数字都小于其相邻数字。
例子:
Input: N = 1
Output: 10
Explanation: All numbers from [0 – 9] satisfy the condition as there is only one digit.
Input: N = 3
Output: 525
朴素方法:解决给定问题的最简单方法是迭代所有可能的N位数字,对于每个这样的数字,检查其所有数字是否满足给定标准。如果发现是真的,那么数一数这些数字。检查所有数字后,打印获得的总数。
时间复杂度: O(10 N *N)
辅助空间: O(1)
高效方法:上述方法也可以通过使用动态规划进行优化,因为它具有重叠的子问题和最优子结构。 The subproblems can be stored in dp[][][] table using memoization where dp[i][prev][sign] stores the result from the i th position till the end, when the previous digit selected, is prev and the variable符号用于指示当前数字是否必须小于或大于前一个数字。请按照以下步骤解决问题:
- 定义一个递归函数,例如, countOfNumbers(digit, prev, sign)具有三个参数:digit、sign 和 prev。
- 检查基本情况,即,如果i的值等于N,则在形成有效的N位数字时返回1 。
- 初始化一个变量,例如val = 0 ,以存储 N 位数字的所有可能计数。
- 如果i为0 ,则可以放置[1 – 9] 中的任何数字,如果N = 1 ,则也可以放置0 。
- 如果i是1 ,则可以放置[0 – 9] 中的任何数字,使得当前数字不等于前一个数字。
- 如果符号的值为1 ,则放置当前数字使其小于前一个数字并将符号更改为0以供下一次递归调用。
- 如果符号的值是0,然后将当前数字,使得它比以前的数字更多,并更改标志1为下一个递归调用。
- 进行有效放置后,递归调用索引(digit + 1)的countOfNumbers函数。
- 作为每个当前递归调用的结果,返回所有可能的有效数字位置的总和。
- 完成上述步骤后,将函数countOfNumbers(0, N, 0, 0)返回的值打印为结果计数。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Declaration of dp table
int dp[100][10][2];
// Function to find the count of all N
// digit numbers such that all the digit
// is less than its adjacent digits
int solve(int i, int n, int prev, bool sign)
{
// Base Case:
// If i = n, then return 1 as valid
// number has been formed
if (i == n) {
return 1;
}
int& val = dp[i][prev][sign];
// If the state has already been
// computed, then return it
if (val != -1)
return val;
// Stores the total count of ways
// for the current recursive call
val = 0;
// If i = 0, any digit from [1-9]
// can be placed and also if N = 1
//, then 0 can also be placed
if (i == 0) {
for (int digit = (n == 1 ? 0 : 1);
digit <= 9;
++digit) {
val += solve(i + 1, n,
digit, sign);
}
}
// If i = 1, any digit from [0-9]
// can be placed such that digit
// is not equal to previous digit
else if (i == 1) {
for (int digit = 0; digit <= 9;
++digit) {
// If the current digit is
// not same as the prev
if (digit != prev) {
val += solve(i + 1, n, digit,
(digit > prev));
}
}
}
else {
// Place the current digit such
// that it is less than the
// previous digit
if (sign == 1) {
for (int digit = prev - 1;
digit >= 0;
--digit) {
val += solve(i + 1, n,
digit, 0);
}
}
// Place current digit such
// that it is more than the
// previous digit
else {
for (int digit = prev + 1;
digit <= 9;
++digit) {
val += solve(i + 1, n,
digit, 1);
}
}
}
// Return the resultant total count
return val;
}
// Function to find all N-digit numbers
// satisfying the given criteria
void countNdigitNumber(int N)
{
// Initialize an array dp[] with
// all elements as -1
memset(dp, -1, sizeof dp);
// Function call to count all
// possible ways
cout << solve(0, N, 0, 0);
}
// Driver Code
int main()
{
int N = 3;
countNdigitNumber(N);
return 0;
}
Java
// Java program for the above approach
import java.util.*;
public class MyClass
{
// Declaration of dp table
static int[][][] dp = new int[100][10][2];
// Function to find the count of all N
// digit numbers such that all the digit
// is less than its adjacent digits
static int solve(int i, int n, int prev, int sign)
{
// Base Case:
// If i = n, then return 1 as valid
// number has been formed
if (i == n) {
return 1;
}
int val = dp[i][prev][sign];
// If the state has already been
// computed, then return it
if (val != -1)
return val;
// Stores the total count of ways
// for the current recursive call
val = 0;
// If i = 0, any digit from [1-9]
// can be placed and also if N = 1
//, then 0 can also be placed
if (i == 0) {
for (int digit = (n == 1 ? 0 : 1);
digit <= 9;
++digit) {
val += solve(i + 1, n,
digit, sign);
}
}
// If i = 1, any digit from [0-9]
// can be placed such that digit
// is not equal to previous digit
else if (i == 1) {
for (int digit = 0; digit <= 9;
++digit) {
// If the current digit is
// not same as the prev
if (digit != prev) {
val += solve(i + 1, n, digit,((digit > prev)?1:0));
}
}
}
else {
// Place the current digit such
// that it is less than the
// previous digit
if (sign == 1) {
for (int digit = prev - 1;
digit >= 0;
--digit) {
val += solve(i + 1, n,
digit, 0);
}
}
// Place current digit such
// that it is more than the
// previous digit
else {
for (int digit = prev + 1;
digit <= 9;
++digit) {
val += solve(i + 1, n,
digit, 1);
}
}
}
// Return the resultant total count
return val;
}
// Function to find all N-digit numbers
// satisfying the given criteria
static void countNdigitNumber(int N)
{
// Initialize an array dp[] with
// all elements as -1
for (int[][] row : dp)
{
for (int[] rowColumn : row)
{
Arrays.fill(rowColumn, -1);
}
}
// Function call to count all
// possible ways
System.out.println(solve(0, N, 0, 0));
}
// Driver Code
public static void main(String args[])
{
int N = 3;
countNdigitNumber(N);
}
}
// This code is contributed by SoumikMondal
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
public class MyClass
{
// Declaration of dp table
static int[,,] dp = new int[100,10,2];
// Function to find the count of all N
// digit numbers such that all the digit
// is less than its adjacent digits
static int solve(int i, int n, int prev, int sign)
{
// Base Case:
// If i = n, then return 1 as valid
// number has been formed
if (i == n) {
return 1;
}
int val = dp[i,prev,sign];
// If the state has already been
// computed, then return it
if (val != -1)
return val;
// Stores the total count of ways
// for the current recursive call
val = 0;
// If i = 0, any digit from [1-9]
// can be placed and also if N = 1
//, then 0 can also be placed
if (i == 0) {
for (int digit = (n == 1 ? 0 : 1);
digit <= 9;
++digit) {
val += solve(i + 1, n,
digit, sign);
}
}
// If i = 1, any digit from [0-9]
// can be placed such that digit
// is not equal to previous digit
else if (i == 1) {
for (int digit = 0; digit <= 9;
++digit) {
// If the current digit is
// not same as the prev
if (digit != prev) {
val += solve(i + 1, n, digit,((digit > prev)?1:0));
}
}
}
else {
// Place the current digit such
// that it is less than the
// previous digit
if (sign == 1) {
for (int digit = prev - 1;
digit >= 0;
--digit) {
val += solve(i + 1, n,
digit, 0);
}
}
// Place current digit such
// that it is more than the
// previous digit
else {
for (int digit = prev + 1;
digit <= 9;
++digit) {
val += solve(i + 1, n,
digit, 1);
}
}
}
// Return the resultant total count
return val;
}
// Function to find all N-digit numbers
// satisfying the given criteria
static void countNdigitNumber(int N)
{
// Initialize an array []dp with
// all elements as -1
for(int i = 0;i<100;i++)
{
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 2; k++)
dp[i,j,k] = -1;
}
}
// Function call to count all
// possible ways
Console.WriteLine(solve(0, N, 0, 0));
}
// Driver Code
public static void Main(String []args)
{
int N = 3;
countNdigitNumber(N);
}
}
// This code is contributed by 29AjayKumar
525
时间复杂度: O(N)
辅助空间: O(N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。