给定两个由N 个整数组成的数组A和B。将 B 的元素本身重新排序,使得重新排序后由(A[i] + B[i]) % N形成的序列在字典序上是最小的。任务是打印尽可能按字典顺序排列的最小序列。
注意:数组元素在 [0, n) 范围内。
例子:
Input: a[] = {0, 1, 2, 1}, b[] = {3, 2, 1, 1}
Output: 1 0 0 2
Reorder B to {1, 3, 2, 1} to get the smallest sequence possible.
Input: a[] = {2, 0, 0}, b[] = {1, 0, 2}
Output: 0 0 2
解决办法:贪心即可解决问题。最初使用散列对数组B的所有数字进行计数,并将它们存储在C++中的集合中,以便lower_bound() [检查元素]和erase() [擦除元素]操作可以在对数时间。
对于数组中的每个元素,使用lower_bound函数检查等于或大于na[i] 的数字。如果没有这样的元素,则取集合中最小的元素。将哈希表中使用的数字的值减 1,如果哈希表的值为 0,则也从集合中删除该元素。
但是有一个例外,如果数组元素为 0,则首先检查 0 然后检查 N,如果它们都不存在,则取最小的元素。
下面是上述方法的实现:
CPP
// C++ implementation of the
// above approach
#include
using namespace std;
// Function to get the smallest
// sequence possible
void solve(int a[], int b[], int n)
{
// Hash-table to count the
// number of occurrences of b[i]
unordered_map mpp;
// Store the element in sorted order
// for using binary search
set st;
// Iterate in the B array
// and count the occurrences and
// store in the set
for (int i = 0; i < n; i++) {
mpp[b[i]]++;
st.insert(b[i]);
}
vector sequence;
// Iterate for N elements
for (int i = 0; i < n; i++) {
// If the element is 0
if (a[i] == 0) {
// Find the nearest number to 0
auto it = st.lower_bound(0);
int el = *it;
sequence.push_back(el % n);
// Decrease the count
mpp[el]--;
// Erase if no more are there
if (!mpp[el])
st.erase(el);
}
// If the element is other than 0
else {
// Find the difference
int x = n - a[i];
// Find the nearest number which can give us
// 0 on modulo
auto it = st.lower_bound(x);
// If no such number occurs then
// find the number closest to 0
if (it == st.end())
it = st.lower_bound(0);
// Get the number
int el = *it;
// store the number
sequence.push_back((a[i] + el) % n);
// Decrease the count
mpp[el]--;
// If no more appears, then erase it from set
if (!mpp[el])
st.erase(el);
}
}
for (auto it : sequence)
cout << it << " ";
}
// Driver Code
int main()
{
int a[] = { 0, 1, 2, 1 };
int b[] = { 3, 2, 1, 1 };
int n = sizeof(a) / sizeof(a[0]);
solve(a, b, n);
return 0;
}
输出:
1 0 0 2