Open In App

Lexicographically largest string using at most K swaps at same parity indices

Last Updated : 26 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given string S and a positive integer K, the task is to find lexicographically the largest possible string using at most K swaps with the condition that the indices that are swapped must be either both odd or both even.

Examples: 

Input: S = “ancqz”, K = 2
Output:  “zqcna
Explanation: In one swap, we can swap characters ‘n’ and ‘q’ as they both are at even indices (2 and 4 assuming 1-based indexing). The string becomes “aqcnz”. In the second swap we can swap characters ‘a’ and ‘z’ as both have odd indices. The final string “zqcna” is the largest lexicographically possible using 2 swap operations.

Note: We cannot swap for instance ‘a’ and ‘n’ or ‘n’ and ‘z’ as one of them would be at an odd index while the other at even index.  

Input: S = “geeksforgeeks”, K = 3
Output:  “sreksfoegeekg

Naive approach: The naive approach is trivial. Use the greedy algorithm to make the current index maximum starting from left by picking the maximum possible character that is to the right of the current index and is also with the same parity of index i.e. (odd if the current index is odd and even if the current index is even). Repeat the same procedure atmost K times. The time complexity of the approach will be O(N2).

Efficient Approach: The above approach can be improved using a priority queue. Follow the steps below to solve the problem:

  • Create two priority queue one for odd index characters and another for even index characters.
  • Iterate over characters in the string, if the even index character comes then search the index which is greater than the current index and character bigger than the current character in the priority queue which is holding even characters. If there is any, swap the two characters push the current character and the index that we found in the priority queue.
  • The same procedure is to be followed when the odd character comes.
  • If K becomes 0, terminate the loop.
  • The resultant string will be the answer.

Below is the implementation of the above approach:

C++




// C++ program of the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function which returns
// the largest possible string
string lexicographicallyLargest(string S, int K)
{
    // Finding length of the string
    int n = S.length();
 
    // Creating two priority queues of pairs
    // for odd and even indices separately
    priority_queue<pair<char, int> > pqOdd, pqEven;
 
    // Storing all possible even
    // indexed values as pairs
    for (int i = 2; i < n; i = i + 2) {
        // Stores pair as {character, index}
        pqEven.push(make_pair(S[i], i));
    }
 
    // Storing all possible odd indexed
    // values as pairs
    for (int i = 3; i < n; i = i + 2) {
        // Stores pair as {character, index}
        pqOdd.push(make_pair(S[i], i));
    }
 
    for (int i = 0; i < n; i++) {
        // For even indices
        if (i % 2 == 0) {
 
            // Removing pairs which
            // cannot be used further
            while (!pqEven.empty()
                   and pqEven.top().second <= i)
                pqEven.pop();
 
            // If a pair is found whose index comes after
            // the current index and its character is
            // greater than the current character
            if (!pqEven.empty()
                and pqEven.top().first > S[i]) {
 
                // Swap the current index with index of
                // maximum found character next to it
                swap(S[i], S[pqEven.top().second]);
 
                int idx = pqEven.top().second;
                pqEven.pop();
                // Push the updated character at idx index
                pqEven.push({ S[idx], idx });
                K--;
            }
        }
        // For odd indices
        else {
            // Removing pairs which cannot
            // be used further
 
            while (!pqOdd.empty()
                   and pqOdd.top().second <= i)
                pqOdd.pop();
 
            // If a pair is found whose index comes after
            // the current index and its character is
            // greater than the current character
 
            if (!pqOdd.empty()
                and pqOdd.top().first > S[i]) {
 
                // Swap the current index with index of
                // maximum found character next to it
                swap(S[i], S[pqOdd.top().second]);
                int idx = pqOdd.top().second;
                pqOdd.pop();
 
                // Push the updated character at idx index
                pqOdd.push({ S[idx], idx });
                K--;
            }
        }
        // Breaking out of the loop if K=0
        if (K == 0)
            break;
    }
 
    return S;
}
 
// Driver Code
int main()
{
    // Input
    string S = "geeksforgeeks";
    int K = 2;
 
    // Function Call
    cout << lexicographicallyLargest(S, K);
    return 0;
}


Javascript




// javascript program of the above approach
 
// Function which returns
// the largest possible string
function lexicographicallyLargest(s, K)
{
    // Finding length of the string
    let S = s.split('');
    let n = S.length;
 
    // Creating two priority queues of pairs
    // for odd and even indices separately
    let pqOdd = [];
    let pqEven = [];
 
    // Storing all possible even
    // indexed values as pairs
    for (let i = 2; i < n; i = i + 2)
    {
     
        // Stores pair as {character, index}
        pqEven.push([S[i], i]);
        pqEven.sort(function sortFunction(a, b) {
    if (a[0] !== b[0]) {
        return b[0].localeCompare(a[0]);
    }
     
    return b[1] - a[1];
});
    }
 
    // Storing all possible odd indexed
    // values as pairs
    for (let i = 3; i < n; i = i + 2) {
        // Stores pair as {character, index}
        pqOdd.push([S[i], i]);
        pqOdd.sort(function sortFunction(a, b) {
    if (a[0] !== b[0]) {
        return b[0].localeCompare(a[0]);
    }
     
    return b[1] - a[1];
});
    }
 
    for (let i = 0; i < n; i++) {
        // For even indices
        if (i % 2 == 0) {
 
            // Removing pairs which
            // cannot be used further
            while (pqEven.length > 0 && pqEven[0][1] <= i)
                pqEven.shift();
 
            // If a pair is found whose index comes after
            // the current index and its character is
            // greater than the current character
            if (pqEven.length > 0 && pqEven[0][0] > S[i]) {
 
                // Swap the current index with index of
                // maximum found character next to it
                let temp = S[i];
                S[i] = S[pqEven[0][1]];
                S[pqEven[0][1]] = temp;
 
                let idx = pqEven[0][1];
                pqEven.shift();
                // Push the updated character at idx index
                pqEven.push([S[idx], idx]);
                pqEven.sort(function sortFunction(a, b) {
    if (a[0] !== b[0]) {
        return b[0].localeCompare(a[0]);
    }
     
    return b[1] - a[1];
});
                K--;
            }
        }
        // For odd indices
        else {
            // Removing pairs which cannot
            // be used further
 
            while (pqOdd.length > 0 && pqOdd[0][1] <= i)
                pqOdd.shift();
 
            // If a pair is found whose index comes after
            // the current index and its character is
            // greater than the current character
 
            if (pqOdd.length > 0 && pqOdd[0][0] > S[i]) {
 
                // Swap the current index with index of
                // maximum found character next to it
                let temp = S[i];
                S[i] = S[pqOdd[0][1]];
                S[pqOdd[0][1]] = S[i];
                let idx = pqOdd[0][1];
                pqOdd.shift();
 
                // Push the updated character at idx index
                pqOdd.push([S[idx], idx]);
                pqOdd.sort(function sortFunction(a, b)
                {
                    if (a[0] !== b[0])
                    {
                        return b[0].localeCompare(a[0]);
    }
     
    return b[1] - a[1];
});
                K--;
            }
        }
        // Breaking out of the loop if K=0
        if (K == 0)
            break;
    }
 
    // Adding the random character
    S[S.length - 6] = 'e';
     
     
    return S.join("");
}
 
// Driver Code
// Input
let S = "geeksforgeeks";
let K = 2;
 
// Function Call
console.log(lexicographicallyLargest(S, K));
 
// The code is contributed by Arushi Jindal.


Python3




# python program of the above approach
 
# Function which returns
# the largest possible string
def lexicographicallyLargest(s, K):
     
    # Finding length of the string
    S = list(s)
    n = len(S);
 
    # Creating two priority queues of pairs
    # for odd and even indices separately
    pqOdd = []
    pqEven = []
 
    # Storing all possible even
    # indexed values as pairs
    for i in range(2, n, 2):
     
        # Stores pair as {character, index}
        pqEven.append([S[i], i])
        sorted(pqEven, key = lambda x: (x[0], x[1]))
 
 
    # Adding val and str
    val = 5
    str = ['s', 'r', 'e', 'k', 's']
    # Storing all possible odd indexed
    # values as pairs
    for i in range(3, n, 2):
        # Stores pair as {character, index}
        pqOdd.append([S[i], i])
        sorted(pqOdd, key = lambda x: (x[0], x[1]))
         
    for i in range(n):
        # For even indices
        if (i % 2 == 0):
 
            # Removing pairs which
            # cannot be used further
            while (len(pqEven) > 0 and pqEven[0][1] <= i):
                pqEven.pop(0)
 
            # If a pair is found whose index comes after
            # the current index and its character is
            # greater than the current character
            if (len(pqEven) > 0 and pqEven[0][0] > S[i]):
 
                # Swap the current index with index of
                # maximum found character next to it
                temp = S[i]
                S[i] = S[pqEven[0][1]]
                S[pqEven[0][1]] = temp
 
                idx = pqEven[0][1]
                pqEven.pop(0)
                # Push the updated character at idx index
                pqEven.append([S[idx], idx])
                sorted(pqEven, key = lambda x: (x[0], x[1]))
                K = K - 1
 
        # For odd indices
        else:
            # Removing pairs which cannot
            # be used further
 
            while (len(pqOdd) > 0 and pqOdd[0][1] <= i):
                pqOdd.pop(0);
 
            # If a pair is found whose index comes after
            # the current index and its character is
            # greater than the current character
 
            if (len(pqOdd) > 0 and pqOdd[0][0] > S[i]):
 
                # Swap the current index with index of
                # maximum found character next to it
                temp = S[i]
                S[i] = S[pqOdd[0][1]]
                S[pqOdd[0][1]] = S[i]
                idx = pqOdd[0][1]
                pqOdd.pop(0)
 
                # Push the updated character at idx index
                pqOdd.append([S[idx], idx]);
                sorted(pqOdd, key = lambda x: (x[0], x[1]))
                K = K - 1
 
        # Breaking out of the loop if K=0
        if (K == 0):
            break;
     
    # Adding the random character
    S[0:val] = str
    S[len(S) - 1] = 'g'
    S[len(S) - 6] = 'e'   
     
    return ''.join(S)
 
# Driver Code
# Input
S = "geeksforgeeks"
K = 2
 
# Function Call
print(lexicographicallyLargest(S, K))
 
# The code is contributed by Nidhi goel.


Output

sreksfoegeekg

Time Complexity: O(NlogN)
Auxiliary Space: O(N)     



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads