给定一组数字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.
一个简单的方法是对一组数字进行排序,然后使用给定的数字从最小到最大的数字移动。我们检查每个数字是否满足给定条件。以这种方式实现它会导致指数时间复杂度。
更好的方法是使用 Modular Arithmetic。因此,我们维护一个队列,我们将在其中存储使用具有给定数字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。
- Do while 队列不为空。
- 从队列中删除前值,对于集合中的每个数字,使用上面写的表达式找到(形成的数字)% 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
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。