📌  相关文章
📜  使用给定的数字集形成的N的最小倍数

📅  最后修改于: 2021-04-22 06:22:14             🧑  作者: Mango

给定一组数字S和一个整数N ,任务是找到最小的正整数(如果存在),该整数仅包含S中的数字并且是N的倍数。请注意,集合中的数字可以多次使用。

例子:

一种简单的方法是对数字集进行排序,然后从使用给定数字形成的最小数字到最大数字。我们检查每个数字是否满足给定条件。以这种方式实现将导致指数级的时间复杂度。

更好的方法是使用模块化算术。因此,我们维护一个队列,在该队列中,我们将存储使用给定数字N的一组数字形成的数字的模数。最初在队列中,将有(个位数)%N,但是我们可以使用来计算(个位数字)%N,

通过使用以上表达式,我们可以计算多个数字的模数值。这是动态编程的一种应用,因为我们正在将解决方案从较小的状态构建为较大的状态。我们维护另一个向量,以确保要插入队列的元素是否已经存在于队列中。它使用散列来确保O(1)的时间复杂度。我们使用了另一个向量对,它也使用散列来存储值,其结构为

此向量将用于构造解决方案:

  1. 对数字集进行排序。
  2. 分别用INT_MAX和{-1,0}初始化两个向量dp和result。
  3. 初始化队列并插入数字%N。
  4. 在队列不为空时执行。
  5. 从队列中除去最前面的值,并使用上面的表达式对集合中的每个数字查找(形成的数字)%N。
  6. 如果在队列为空之前没有得到0作为模量值,则不存在最小的正数,否则从第0个索引开始跟踪结果矢量,直到在任何索引处获得-1。
  7. 将所有这些值放在另一个向量中并将其反转。
  8. 这是我们必需的解决方案。

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
  
// Function to return the required number
int findSmallestNumber(vector& arr, int n)
{
  
    // Initialize both vectors with their initial values
    vector dp(n, numeric_limits::max() - 5);
    vector > result(n, make_pair(-1, 0));
  
    // Sort the vector of digits
    sort(arr.begin(), arr.end());
  
    // Initialize the queue
    queue q;
    for (auto i : arr) {
        if (i != 0) {
  
            // If modulus value is not present
            // in the queue
            if (dp[i % n] > 1e9) {
  
                // Compute digits modulus given number and
                // update the queue and vectors
                q.push(i % n);
                dp[i % n] = 1;
                result[i % n] = { -1, i };
            }
        }
    }
  
    // While queue is not empty
    while (!q.empty()) {
  
        // Remove the first element of the queue
        int u = q.front();
        q.pop();
        for (auto i : arr) {
  
            // Compute new modulus values by using old queue
            // values and each digit of the set
            int v = (u * 10 + i) % n;
  
            // If value is not present in the queue
            if (dp[u] + 1 < dp[v]) {
                dp[v] = dp[u] + 1;
                q.push(v);
                result[v] = { u, i };
            }
        }
    }
  
    // If required condition can't be satisfied
    if (dp[0] > 1e9)
        return -1;
    else {
  
        // Initialize new vector
        vector ans;
        int u = 0;
        while (u != -1) {
  
            // Constructing the solution by backtracking
            ans.push_back(result[u].second);
            u = result[u].first;
        }
  
        // Reverse the vector
        reverse(ans.begin(), ans.end());
        for (auto i : ans) {
  
            // Return the required number
            return i;
        }
    }
}
  
// Driver code
int main()
{
    vector arr = { 5, 2, 3 };
    int n = 12;
  
    cout << findSmallestNumber(arr, n);
  
    return 0;
}


Python3
# Python3 implementation of the approach 
  
# Function to return the required number 
def findSmallestNumber(arr, n): 
   
    # Initialize both vectors with their initial values 
    dp = [float('inf')] * n 
    result = [(-1, 0)] * n 
  
    # Sort the vector of digits 
    arr.sort() 
  
    # Initialize the queue 
    q = [] 
    for i in arr:  
        if i != 0:  
  
            # If modulus value is not 
            # present in the queue 
            if dp[i % n] > 10 ** 9:  
  
                # Compute digits modulus given number 
                # and update the queue and vectors 
                q.append(i % n) 
                dp[i % n] = 1 
                result[i % n] = -1, i  
               
    # While queue is not empty 
    while len(q) > 0:
  
        # Remove the first element of the queue 
        u = q.pop(0) 
        for i in arr:  
  
            # Compute new modulus values by using old 
            # queue values and each digit of the set 
            v = (u * 10 + i) % n 
  
            # If value is not present in the queue 
            if dp[u] + 1 < dp[v]:  
                dp[v] = dp[u] + 1 
                q.append(v) 
                result[v] = u, i  
  
    # If required condition can't be satisfied 
    if dp[0] > 10 ** 9:
        return -1 
    else:  
  
        # Initialize new vector 
        ans = [] 
        u = 0 
        while u != -1:  
  
            # Constructing the solution by backtracking 
            ans.append(result[u][1]) 
            u = result[u][0] 
          
        # Reverse the vector 
        ans = ans[::-1] 
        for i in ans:  
  
            # Return the required number 
            return i 
           
# Driver code 
if __name__ == "__main__": 
   
    arr = [5, 2, 3]  
    n = 12 
  
    print(findSmallestNumber(arr, n)) 
  
# This code is contributed by Rituraj Jain


输出:
2