📌  相关文章
📜  长度为N且值小于K的整数的计数,使得它们仅包含给定集合中的数字

📅  最后修改于: 2021-04-29 14:00:20             🧑  作者: Mango

给定一组以排序顺序排列的数字A []以及两个整数NK ,任务是找出可能有多少个长度N的值小于K的数字,并且这些数字仅来自给定的数字。请注意,您可以多次使用相同的数字。

例子:

方法:dA []的大小。我们可以将这个问题分为三个简单的案例。

  1. N大于K的长度时,很明显,如果N的长度大于k的长度或d等于0,则不可能有这样的数字。
  2. N小于K的长度时,则长度N的所有数字的所有可能组合都是有效的。另外,我们必须记住, 0不能放在首位。因此,如果A []包含0 ,则可以用(d – 1)方式填充第一位。由于允许重复并且0可以占据其他位置,因此可以用d * d *…* d(N – 1)次(即d N – 1种方式)填充其余的N – 1个位置。因此,如果A []包含0否则d N,则答案为(d – 1)*(d N – 1 )
  3. N等于K的长度时,这是最棘手的部分。我们需要为这部分使用动态编程。构造一个K的数字数组。我们称它为digit [] 。令First(i)为通过取其前i个数字形成的数字。让lower [i]表示A []中小于i的元素数量。
    例如,423的First(2)是42。如果A [] = {0,2},则lower [0] = 0,lower [1] = 1,lower [2] = 1,lower [3] = 2 。
    通过动态编程生成N位数字。令dp [i]表示长度i的总数,该总数小于K的i个数字。
    dp [i]中的元素可以通过两种情况生成:
    • 对于First(i – 1)小于K的First(i – 1)的所有数字,我们可以在ith索引处放置任何数字。因此, dp [i] = dp [i] +(dp [i – 1] * d)
    • 对于那些首先数字(I – 1)是一样的第一(I – 1)K,我们只能把那些不是数字[I]小数字。因此, dp [i] = dp [i] + lower [digit [i]]

      最后,我们返回dp [N]。注意:对于第一个索引,如果N不为1并且dp [0] = 0,则不包括0。

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
  
#define MAX 10
  
// Function to convert a number into vector
vector numToVec(int N)
{
    vector digit;
  
    // Push all the digits of N from the end
    // one by one to the vector
    while (N != 0) {
        digit.push_back(N % 10);
        N = N / 10;
    }
  
    // If the original number was 0
    if (digit.size() == 0)
        digit.push_back(0);
  
    // Reverse the vector elements
    reverse(digit.begin(), digit.end());
  
    // Return the required vector
    return digit;
}
  
// Function to return the count of B length integers
// which are less than C and they
// contain digits from set A[] only
int solve(vector& A, int B, int C)
{
    vector digit;
    int d, d2;
  
    // Convert number to digit array
    digit = numToVec(C);
    d = A.size();
  
    // Case 1: No such number possible as the
    // generated numbers will always
    // be greater than C
    if (B > digit.size() || d == 0)
        return 0;
  
    // Case 2: All integers of length B are valid
    // as they all are less than C
    else if (B < digit.size()) {
        // contain 0
        if (A[0] == 0 && B != 1)
            return (d - 1) * pow(d, B - 1);
        else
            return pow(d, B);
    }
  
    // Case 3
    else {
        int dp[B + 1] = { 0 };
        int lower[MAX + 1] = { 0 };
  
        // Update the lower[] array such that
        // lower[i] stores the count of elements
        // in A[] which are less than i
        for (int i = 0; i < d; i++)
            lower[A[i] + 1] = 1;
        for (int i = 1; i <= MAX; i++)
            lower[i] = lower[i - 1] + lower[i];
  
        bool flag = true;
        dp[0] = 0;
        for (int i = 1; i <= B; i++) {
            d2 = lower[digit[i - 1]];
            dp[i] = dp[i - 1] * d;
  
            // For first index we can't use 0
            if (i == 1 && A[0] == 0 && B != 1)
                d2 = d2 - 1;
  
            // Whether (i-1) digit of generated number
            // can be equal to (i - 1) digit of C
            if (flag)
                dp[i] += d2;
  
            // Is digit[i - 1] present in A ?
            flag = (flag & (lower[digit[i - 1] + 1]
                            == lower[digit[i - 1]] + 1));
        }
        return dp[B];
    }
}
  
// Driver code
int main()
{
  
    // Digits array
    vector A = { 0, 1, 2, 5 };
    int N = 2;
    int k = 21;
  
    cout << solve(A, N, k);
  
    return 0;
}


Java
// Java implementation of the approach
import java.util.*;
  
class GFG 
{
static int MAX = 10;
  
// Function to convert a number into vector
static Vector numToVec(int N)
{
    Vector digit = new Vector();
  
    // Push all the digits of N from the end
    // one by one to the vector
    while (N != 0)
    {
        digit.add(N % 10);
        N = N / 10;
    }
  
    // If the original number was 0
    if (digit.size() == 0)
        digit.add(0);
  
    // Reverse the vector elements
    Collections.reverse(digit);
  
    // Return the required vector
    return digit;
}
  
// Function to return the count 
// of B length integers which are 
// less than C and they contain 
// digits from set A[] only
static int solve(Vector A, int B, int C)
{
    Vector digit = new Vector();
    int d, d2;
  
    // Convert number to digit array
    digit = numToVec(C);
    d = A.size();
  
    // Case 1: No such number possible as the
    // generated numbers will always
    // be greater than C
    if (B > digit.size() || d == 0)
        return 0;
  
    // Case 2: All integers of length B are valid
    // as they all are less than C
    else if (B < digit.size()) 
    {
        // contain 0
        if (A.get(0) == 0 && B != 1)
            return (int) ((d - 1) * Math.pow(d, B - 1));
        else
            return (int) Math.pow(d, B);
    }
  
    // Case 3
    else 
    {
        int []dp = new int[B + 1];
        int []lower = new int[MAX + 1];
  
        // Update the lower[] array such that
        // lower[i] stores the count of elements
        // in A[] which are less than i
        for (int i = 0; i < d; i++)
            lower[A.get(i) + 1] = 1;
        for (int i = 1; i <= MAX; i++)
            lower[i] = lower[i - 1] + lower[i];
  
        boolean flag = true;
        dp[0] = 0;
        for (int i = 1; i <= B; i++) 
        {
            d2 = lower[digit.get(i - 1)];
            dp[i] = dp[i - 1] * d;
  
            // For first index we can't use 0
            if (i == 1 && A.get(0) == 0 && B != 1)
                d2 = d2 - 1;
  
            // Whether (i-1) digit of generated number
            // can be equal to (i - 1) digit of C
            if (flag)
                dp[i] += d2;
  
            // Is digit[i - 1] present in A ?
            flag = (flag & (lower[digit.get(i - 1) + 1] == 
                            lower[digit.get(i - 1)] + 1));
        }
        return dp[B];
    }
}
  
// Driver code
public static void main(String[] args) 
{
    Integer arr[] = { 0, 1, 2, 5 };
    // Digits array
    Vector A = new Vector<>(Arrays.asList(arr));
    int N = 2;
    int k = 21;
  
    System.out.println(solve(A, N, k));
}
}
  
// This code is contributed
// by PrinciRaj1992


Python3
# Python3 implementation of the approach
MAX=10
  
# Function to convert a number into vector
def numToVec(N):
      
    digit = []
  
    # Push all the digits of N from the end
    # one by one to the vector
    while (N != 0):
        digit.append(N % 10)
        N = N // 10
  
    # If the original number was 0
    if (len(digit) == 0):
        digit.append(0)
  
    # Reverse the vector elements
    digit = digit[::-1]
  
    # Return the required vector
    return digit
  
  
# Function to return the count of B length integers
# which are less than C and they
# contain digits from set A[] only
def solve(A, B, C):
    d, d2 = 0,0
  
    # Convert number to digit array
    digit = numToVec(C)
    d = len(A)
  
    # Case 1: No such number possible as the
    # generated numbers will always
    # be greater than C
    if (B > len(digit) or d == 0):
        return 0
  
    # Case 2: All integers of length B are valid
    # as they all are less than C
    elif (B < len(digit)):
        # contain 0
        if (A[0] == 0 and B != 1):
            return (d - 1) * pow(d, B - 1)
        else:
            return pow(d, B)
  
    # Case 3
    else :
        dp=[0 for i in range(B + 1)]
        lower=[0 for i in range(MAX + 1)]
  
        # Update the lower[] array such that
        # lower[i] stores the count of elements
        # in A[] which are less than i
        for i in range(d):
            lower[A[i] + 1] = 1
        for i in range(1, MAX+1):
            lower[i] = lower[i - 1] + lower[i]
  
        flag = True
        dp[0] = 0
        for i in range(1, B+1):
            d2 = lower[digit[i - 1]]
            dp[i] = dp[i - 1] * d
  
            # For first index we can't use 0
            if (i == 1 and A[0] == 0 and B != 1):
                d2 = d2 - 1
  
            # Whether (i-1) digit of generated number
            # can be equal to (i - 1) digit of C
            if (flag):
                dp[i] += d2
  
            # Is digit[i - 1] present in A ?
            flag = (flag & (lower[digit[i - 1] + 1] == lower[digit[i - 1]] + 1))
          
        return dp[B]
  
# Driver code
  
# Digits array
A =[0, 1, 2, 5]
N = 2
k = 21
  
print(solve(A, N, k))
  
# This code is contributed by mohit kumar 29


C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
  
class GFG 
{
static int MAX = 10;
  
// Function to convert a number into vector
static List numToVec(int N)
{
    List digit = new List();
  
    // Push all the digits of N from the end
    // one by one to the vector
    while (N != 0)
    {
        digit.Add(N % 10);
        N = N / 10;
    }
  
    // If the original number was 0
    if (digit.Count == 0)
        digit.Add(0);
  
    // Reverse the vector elements
    digit.Reverse();
  
    // Return the required vector
    return digit;
}
  
// Function to return the count 
// of B length integers which are 
// less than C and they contain 
// digits from set A[] only
static int solve(List A, int B, int C)
{
    List digit = new List();
    int d, d2;
  
    // Convert number to digit array
    digit = numToVec(C);
    d = A.Count;
  
    // Case 1: No such number possible as the
    // generated numbers will always
    // be greater than C
    if (B > digit.Count || d == 0)
        return 0;
  
    // Case 2: All integers of length B are valid
    // as they all are less than C
    else if (B < digit.Count) 
    {
        // contain 0
        if (A[0] == 0 && B != 1)
            return (int) ((d - 1) * Math.Pow(d, B - 1));
        else
            return (int) Math.Pow(d, B);
    }
  
    // Case 3
    else
    {
        int []dp = new int[B + 1];
        int []lower = new int[MAX + 1];
  
        // Update the lower[] array such that
        // lower[i] stores the count of elements
        // in A[] which are less than i
        for (int i = 0; i < d; i++)
            lower[A[i] + 1] = 1;
        for (int i = 1; i <= MAX; i++)
            lower[i] = lower[i - 1] + lower[i];
  
        Boolean flag = true;
        dp[0] = 0;
        for (int i = 1; i <= B; i++) 
        {
            d2 = lower[digit[i-1]];
            dp[i] = dp[i - 1] * d;
  
            // For first index we can't use 0
            if (i == 1 && A[0] == 0 && B != 1)
                d2 = d2 - 1;
  
            // Whether (i-1) digit of generated number
            // can be equal to (i - 1) digit of C
            if (flag)
                dp[i] += d2;
  
            // Is digit[i - 1] present in A ?
            flag = (flag & (lower[digit[i-1] + 1] == 
                            lower[digit[i-1]] + 1));
        }
        return dp[B];
    }
}
  
// Driver code
public static void Main(String[] args) 
{
    int []arr = { 0, 1, 2, 5 };
      
    // Digits array
    List A = new List(arr);
    int N = 2;
    int k = 21;
  
    Console.WriteLine(solve(A, N, k));
}
}
  
// This code is contributed by Rajput-Ji


输出:
5

时间复杂度: O(N)