Given a string S of size N, having lowercase alphabets, the task is to find the lexicographically minimum string after moving a subsequence to the end of the string only once.
Example:
Input: N = 3, S = “asa”
Output: aas
Explanation: The optimal subsequence is “s”.
Removed, and added at last. Hence the final string is ‘aa’ + ‘s’ =’aas’Input: N = 7, S = “fabccac”
Output: aacfbcc
Explanation: The optimal subsequence is “fbcc”.
Any other subsequence will not give the minimum
Hence the final string is ‘aac’ + ‘fbcc’ = ‘aacfbcc’
Approach: The problem can be solved based on the following observation:
To find the lexicographically minimum string the selected subsequence should follow the pattern.
- The 1st character of the selected subsequence to be removed should be same or greater than the last character of the retaining subsequence.
- The non selected subsequence shall form a non-decreasing sequence.
Follow the steps to solve the problem:
- Initialize a boolean array to maintain the position of characters if included in the subsequence to be shuffled or not.
- Maintain a stack for finding non-decreasing subsequence of retaining characters
- At every character, pop all characters greater than the current character from the stack.
Below is the implementation for the above approach:
// C++ code for the above approach #include <bits/stdc++.h> using namespace std;
// Function to find lexicographically minimum string LexMin( int n, string s)
{ // Boolean array for storing positions
// and frequencies
vector< int > last(26, -1);
for ( int i = 0; i < n; i++) {
last[s[i] - 'a' ] = i;
}
int dig = 0;
int mx = 26;
// ans for storing resultant string
// ans1 for leftout and ans2 for picked up
string ans = s, ans1, ans2;
for ( int i = 0; i < n; i++) {
// For every i we will find its
// last occurrence last[dig]
while (dig < 26 && i > last[dig])
dig++;
if (dig == mx) {
string ans3 = ans2, ans4;
for ( int j = i; j < n; j++) {
// Adding the character
if (s[j] == ( 'a' + mx)) {
ans4.push_back(s[j]);
}
else {
ans3.push_back(s[j]);
}
}
// Remove the other half and
// store the substring upto i
ans2 += s.substr(i);
// Find out the minimum
// and put it into ans
ans = min(ans, ans1
+ min(ans2, ans4 + ans3));
break ;
}
else if (dig > mx) {
ans = min(ans, ans1
+ ans2 + s.substr(i));
break ;
}
// ans1 holds value retaining values
if (s[i] == ( 'a' + dig)) {
ans1.push_back(s[i]);
}
else {
if (mx == 26)
mx = (s[i] - 'a' );
ans2.push_back(s[i]);
}
// Corner cases
if (i == n - 1)
ans = min(ans, ans1 + ans2);
}
// Return the ans
return ans;
} // Driver code int main()
{ int N = 3;
string s = "asa" ;
// Function call
cout << LexMin(N, s) << endl;
return 0;
} |
import java.util.Arrays;
class Main {
// Function to find lexicographically minimum
static String LexMin( int n, String s) {
// Boolean array for storing positions
// and frequencies
int [] last = new int [ 26 ];
Arrays.fill(last, - 1 );
for ( int i = 0 ; i < n; i++) {
last[s.charAt(i) - 'a' ] = i;
}
// ans for storing resultant string
// ans1 for leftout and ans2 for picked up
int dig = 0 ;
int mx = 26 ;
// ans for storing resultant string
// ans1 for leftout and ans2 for picked up
String ans = s, ans1 = "" , ans2 = "" ;
for ( int i = 0 ; i < n; i++) {
// For every i we will find its
// last occurrence last[dig]
while (dig < 26 && i > last[dig]) {
dig++;
}
if (dig == mx) {
String ans3 = ans2, ans4 = "" ;
for ( int j = i; j < n; j++) {
if (s.charAt(j) == ( 'a' + mx)) {
ans4 += s.charAt(j);
} else {
ans3 += s.charAt(j);
}
}
// Remove the other half and
// store the substring upto i
ans2 += s.substring(i);
// Find out the minimum
// and put it into ans
ans = min(ans, ans1 + min(ans2, ans4 + ans3));
break ;
} else if (dig > mx) {
ans = min(ans, ans1 + ans2 + s.substring(i));
break ;
}
// ans1 holds value retaining values
if (s.charAt(i) == ( 'a' + dig)) {
ans1 += s.charAt(i);
} else {
if (mx == 26 ) {
mx = (s.charAt(i) - 'a' );
}
ans2 += s.charAt(i);
}
// Corner cases
if (i == n - 1 ) {
ans = min(ans, ans1 + ans2);
}
}
return ans;
}
static String min(String a, String b) {
return a.compareTo(b) < 0 ? a : b;
}
// Driver code public static void main(String[] args) {
int N = 3 ;
String s = "asa" ;
System.out.println(LexMin(N, s));
}
} //This code is contributed by Edula Vinay Kumar Reddy |
# Python3 code for the above approach # Function to find lexicographically minimum def LexMin(n, s) :
# Boolean array for storing positions
# and frequencies
last = [ - 1 ] * 26 ;
for i in range (n) :
last[ ord (s[i]) - ord ( 'a' )] = i;
dig = 0 ;
mx = 26 ;
# ans for storing resultant string
# ans1 for leftout and ans2 for picked up
ans = s;
ans1,ans2 = " "," ";
for i in range (n) :
# For every i we will find its
# last occurrence last[dig]
while (dig < 26 and i > last[dig]) :
dig + = 1 ;
if (dig = = mx) :
ans3 = ans2;
ans4 = "";
for j in range ( 1 , n) :
# Adding the character
if ( ord (s[j]) = = ( ord ( 'a' ) + mx)) :
ans4 + = s[j] ;
else :
ans3 + = s[j];
# Remove the other half and
# store the substring upto i
ans2 + = s[:i];
# Find out the minimum
# and put it into ans
ans = min (ans, ans1 + min (ans2, ans4 + ans3));
break ;
elif (dig > mx) :
ans = min (ans, ans1 + ans2 + s[:i]);
break ;
# ans1 holds value retaining values
if ( ord (s[i]) = = ( ord ( 'a' ) + dig)) :
ans1 + = s[i];
else :
if (mx = = 26 ) :
mx = ( ord (s[i]) - ord ( 'a' ));
ans2 + = s[i];
# Corner cases
if (i = = n - 1 ) :
ans = min (ans, ans1 + ans2);
# Return the ans
return ans;
# Driver code if __name__ = = "__main__" :
N = 3 ;
s = "asa" ;
# Function call
print (LexMin(N, s));
# This code is contributed by AnkThon
|
// C# code for the above approach using System;
class Program
{ static string LexMin( int n, string s)
{
// Boolean array for storing positions
// and frequencies
int [] last = new int [26];
for ( int i = 0; i < 26; i++)
{
last[i] = -1;
}
for ( int i = 0; i < n; i++)
{
last[s[i] - 'a' ] = i;
}
int dig = 0;
int mx = 26;
// ans for storing resultant string
// ans1 for leftout and ans2 for picked up
string ans = s;
string ans1 = "" , ans2 = "" ;
for ( int i = 0; i < n; i++)
{
// For every i we will find its
// last occurrence last[dig]
while (dig < 26 && i > last[dig])
{
dig++;
}
if (dig == mx)
{
string ans3 = ans2;
string ans4 = "" ;
for ( int j = 1; j < n; j++)
{
// Adding the character
if (s[j] == 'a' + mx)
{
ans4 += s[j];
}
else
{
ans3 += s[j];
}
}
// Remove the other half and
// store the substring upto i
ans2 += s.Substring(0, i);
// Find out the minimum
// and put it into ans
ans = Min(ans, ans1 + Min(ans2, ans4 + ans3));
break ;
}
else if (dig > mx)
{
ans = Min(ans, ans1 + ans2 + s.Substring(0, i));
break ;
}
// ans1 holds value retaining values
if (s[i] == 'a' + dig)
{
ans1 += s[i];
}
else
{
if (mx == 26)
{
mx = s[i] - 'a' ;
}
ans2 += s[i];
}
// Corner cases
if (i == n - 1)
{
ans = Min(ans, ans1 + ans2);
}
}
// Return the ans
return ans;
}
static string Min( string a, string b)
{
if ( string .Compare(a, b) < 0)
{
return a;
}
else
{
return b;
}
}
static void Main( string [] args)
{
int N = 3;
string s = "asa" ;
// Function call
Console.WriteLine(LexMin(N, s));
}
} // This code is contributed by rishabmalhdijo |
<script> // JavaScript code for the above approach // Function to find lexicographically minimum function LexMin(n,s)
{ // Boolean array for storing positions
// and frequencies
let last = new Array(26).fill(-1);
for (let i = 0; i < n; i++) {
last[s.charCodeAt(i) - 'a' .charCodeAt(0)] = i;
}
let dig = 0;
let mx = 26;
// ans for storing resultant string
// ans1 for leftout and ans2 for picked up
let ans = s, ans1 = "" , ans2 = "" ;
for (let i = 0; i < n; i++) {
// For every i we will find its
// last occurrence last[dig]
while (dig < 26 && i > last[dig])
dig++;
if (dig == mx) {
let ans3 = ans2, ans4;
for (let j = 1; j < n; j++) {
// Adding the character
if (s.charCodeAt(j) == ( 'a' .charCodeAt(0) + mx)) {
ans4 += s[j];
}
else {
ans3 += s[j];
}
}
// Remove the other half and
// store the substring upto i
ans2 += s.substring(0,i);
// Find out the minimum
// and put it into ans
ans = ans1;
if (ans2 > ans4 + ans3)
ans2 = ans4 + ans3;
if (ans > ans2)
ans = ans2;
break ;
}
else if (dig > mx) {
if (ans > ans1 + ans2 + s.substring(0,i))
ans = ans1 + ans2 + s.substring(0,i)
break ;
}
// ans1 holds value retaining values
if (s.charCodeAt(i) == ( 'a' .charCodeAt(0) + dig)) {
ans1 += s[i];
}
else {
if (mx == 26)
mx = (s.charCodeAt(i) - 'a' .charCodeAt(0));
ans2 += s[i];
}
// Corner cases
if (i == n - 1){
if (ans > ans1 + ans2)
ans = ans1 + ans2;
}
}
// Return the ans
return ans;
} // Driver code let N = 3; let s = "asa" ;
// Function call document.write(LexMin(N, s), "</br>" );
// This code is contributed by shinjanpatra </script> |
aas
Time Complexity: O(N)
Auxiliary Space: O(N)