Generate Lexicographically Smallest Permutation of 1 to N where Elements follow given Relation


In this topic, we seek the relationally constrained lexicographically minimal permutation of numbers from 1 to N. The relation describes the relative order of certain of the permutation's components. We ensure that the resulting permutation is the least possible when comparing lexicographically by carefully organising the numbers based on this relation. In order to achieve the lowest feasible arrangement of the numbers, the best sequence must be found that both meets the relation restrictions and does so. To efficiently produce the intended outcome, the procedure entails thorough analysis and element selection.

Methods Used

  • Greedy Approach

  • Backtracking

Greedy Approach

We take a methodical approach while using the greedy strategy to generate the lexicographically minimum permutation from 1 to N with a given relation. We repeatedly choose the lowest element among the remaining candidates at each stage that satisfies the specified relation. This smallest valid element is added to the permutation, but it is later disregarded. The process is repeated with the smallest elements after that, making sure they preserve the required relationship with the elements that were previously introduced. In this manner, we consistently select the shortest valid element and create the lowest lexicographic permutation while maintaining the given relation. The intended outcome that satisfies the lexicographical ordering and the stated relation is ensured by repeating this process until all items are represented in the final permutation.

Algorithm

  • Initialise a blank list to hold the generated permutation

  • Arrange the elements according to the supplied relation in ascending order.

  • Continue iterating through the elements that have been sorted.

  • For each element, determine whether including it in the permutation will satisfy the relationship with already−added elements.

  • If the relation is met, add the element to the list of permutations and disregard it.

  • Continue performing steps 4−5 until the permutation includes each of the items.

  • The list that results reflects the permutation from 1 to N that is lexicographically smallest.

Example

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

bool checkRelation(const vector<int>& permutation, int num) {
    
    return true; 
}

vector<int> generateLexicographicallySmallestPermutation(int N) {
    vector<int> permutation;
    for (int i = 1; i <= N; ++i) {
        permutation.push_back(i);
    }

    sort(permutation.begin(), permutation.end(), [](int a, int b) {
        return checkRelation({a}, b);
    });

    return permutation;
}

int main() {
    int N = 5; 

    vector<int> result = generateLexicographicallySmallestPermutation(N);

    cout << "Lexicographically Smallest Permutation: ";
    for (int num : result) {
        cout << num << " ";
    }
    cout << endl;

    return 0;
}

Output

Lexicographically Smallest Permutation: 5 4 3 2 1 

Backtracking

Backtracking is a useful algorithmic strategy for locating the 1 to N lexicographically minimum permutation while maintaining a particular relation. It adopts a methodical approach, making decisions for each location in the permutation and considering every alternative. The method goes back to the previous place and looks at additional options if a chosen element results in an erroneous answer. It eventually determines the ideal configuration that fulfils the required relation by thoroughly studying all permutations and continuously improving the arrangement. In order to find the most plausible permutations with the least lexical footprint, backtracking ensures a thorough search. This method is especially useful in situations when there are many possible outcomes since it quickly pinpoints the desired outcome while pruning ineffective alternatives.

Algorithm

  • Recognise and identify the relation provided, which specifies the relative order of components in the permutation.

  • Create the variables and data structures needed to keep track of the current permutation and other restrictions.

  • Select the first element of the permutation to start the backtracking procedure.

  • Try every element that satisfies the specified relation for each location in the permutation.

  • Make sure the element you've picked doesn't go against any rules or interfere with the relationship.

  • Update the permutation by adding the selected element, if it is valid, and moving on to the following slot.

  • Recursively move to the following location in the permutation and repeat steps 4 through 6 to continue the backtracking process.

  • The current permutation is a contender for the lexicographically smallest one when all places are filled.

  • If a smaller permutation is identified, compare the current permutation to the best one so far and update the result.

  • Take away the most recent element added to the current permutation and return to the original place to consider alternative options.

  • Examine every combination until all choices have been considered.

  • As the final output, after the backtracking procedure is finished, return the lexicographically minimal permutation.

Example

#include <iostream>
#include <vector>
using namespace std;

vector<int> permutation;
vector<bool> used;

bool isRelationSatisfied(int a, int b) {
    return a > b;
}

void generatePermutation(int N) {
    if (permutation.size() == N) {
        for (int num : permutation) {
            cout << num << " ";
        }
        cout << endl;
        return;
    }

    for (int i = 1; i <= N; i++) {
        if (!used[i] && (permutation.empty() || isRelationSatisfied(permutation.back(), i))) {
            permutation.push_back(i);
            used[i] = true;
            generatePermutation(N);
            permutation.pop_back();
            used[i] = false;
        }
    }
}

int main() {
    int N = 4;
    used.resize(N + 1, false);
    generatePermutation(N);
    return 0;
}

Output

4 3 2 1

Conclusion

In order to create the lexicographically minimal permutation of 1 to N that adheres to a particular relation, one of the Greedy Approach or Backtracking must be used. The Greedy Approach effectively creates the smallest permutation by choosing the smallest valid element at each step. On the other hand, Backtracking carefully investigates every variant to identify the best, lexicographically smallest arrangement. Depending on the intricacy of the relation and the quantity of viable permutations, both techniques have specific advantages. We can easily produce the required, lexicographically minimal permutation that fulfils the specified relation by carefully analysing the issue and using the right strategy.

Updated on: 02-Aug-2023

144 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements