Find the lexicographically smallest sequence which can be formed by re-arranging elements of second array

Given two arrays A and B of N integers. Reorder the elements of B in itself in such a way that the sequence formed by (A[i] + B[i]) % N after re-ordering is the smallest lexicographically. The task is to print the lexicographically smallest sequence possible.

Note: The array elements are in range [0, n).

Examples:

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

Approach: The problem can be solved greedily. Initially keep a count of all the numbers of array B using hashing, and store them in the set in C++, so that lower_bound() [ To check for an element ] and erase() [ To erase an element ] operations can be done in logarithmic time.

For every element in the array, check for a number equal or greater than n-a[i] using lower_bound function. If there are no such elements then take the smallest element in the set. Decrease the value by 1 in the hash table for the number used, if the hash table’s value is 0, then erase the element from the set also.

However there is an exception if the array element is 0, then check for 0 at the first then for N, if both of them are not there, then take the smallest element.

Below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the
// above approach
  
#include <bits/stdc++.h>
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<int, int> mpp;
  
    // Store the element in sorted order
    // for using binary search
    set<int> 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<int> 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 appers, 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;
}
chevron_right

Output:
1 0 0 2



Striver(underscore)79 at Codechef and codeforces D

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : Akanksha_Rai



Article Tags :