给定一组数字S和一个整数N ,任务是找到最小的正整数(如果存在),该整数仅包含S中的数字并且是N的倍数。请注意,集合中的数字可以多次使用。
例子:
Input: S[] = {5, 2, 3}, N = 12
Output: 252
We can observe that 252 is formed using {2, 5} and is a multiple of 12
Input: S[] = {1, 3, 5, 7, 9}, N = 2
Output: -1
Multiple of 2 would always be an even number but from the given set of digits even number can’t be formed.
一种简单的方法是对数字集进行排序,然后从使用给定数字形成的最小数字到最大数字。我们检查每个数字是否满足给定条件。以这种方式实现将导致指数级的时间复杂度。
更好的方法是使用模块化算术。因此,我们维护一个队列,在该队列中,我们将存储使用给定数字N的一组数字形成的数字的模数。最初在队列中,将有(个位数)%N,但是我们可以使用来计算(个位数字)%N,
New_mod = (Old_mod * 10 + digit) % N
通过使用以上表达式,我们可以计算多个数字的模数值。这是动态编程的一种应用,因为我们正在将解决方案从较小的状态构建为较大的状态。我们维护另一个向量,以确保要插入队列的元素是否已经存在于队列中。它使用散列来确保O(1)的时间复杂度。我们使用了另一个向量对,它也使用散列来存储值,其结构为
result[new_mod] = { current_element_of_queue, digit}
此向量将用于构造解决方案:
- 对数字集进行排序。
- 分别用INT_MAX和{-1,0}初始化两个向量dp和result。
- 初始化队列并插入数字%N。
- 在队列不为空时执行。
- 从队列中除去最前面的值,并使用上面的表达式对集合中的每个数字查找(形成的数字)%N。
- 如果在队列为空之前没有得到0作为模量值,则不存在最小的正数,否则从第0个索引开始跟踪结果矢量,直到在任何索引处获得-1。
- 将所有这些值放在另一个向量中并将其反转。
- 这是我们必需的解决方案。
下面是上述方法的实现:
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