Lexicographically smallest string formed by reversing Substrings of string S exactly K times
Given a string S and an integer K, the task is to find the lexicographically smallest string possible after reversing any substring of any length exactly K times.
Examples:
Input: S = “fgazcbdfge”, K = 3
Output: abcdgfzfge
Explanation: After 1st operation: S = “agfzcbdfge”, in S select S[0 – 2] = “fga” and reverse it
After 2nd operation: S = “abczfgdfge”, in S select S[2 – 4] = “fzc” and reverse it
After 3rd operation: S = “abcdgfzfge”, in S select S[3 – 6] = “zfgd” and reverse it.Input: S = “abcdefg”, K = 5
Output: abcdefg
Explanation: The string is already lexicographically minimum possible.
Hence pick any 5 substrings having length 1. So the string will remain unchanged.
Approach: To form the lexicographically smallest string in K steps, in each step select an integer L where S[L] is the character before which all characters are in sorted order and an integer R where S[R] is the character which has to be placed at S[L+1] so that all character till S[L+1] will be in sorted order. Reverse the substring S[L..R] in each step and finally, the required string will be obtained. Follow the below steps to solve the problem:
- Let the given string be S, create another string S1 equal to S then sort S1 in increasing order.
- This algorithm requires three nested loops, the outer loop will run from 0 to K (number of operations)
- In every operation, search for two integers L and R, after they have been found we reverse the substring S[L … R] and continue the same for subsequent operations.
- Using two nested loops search for characters of S1 in S depending upon the number of operations.
- Since there is the need to only reverse one substring in one operation, just find one character of S1 in S which is S[R] (the character which has to be placed after already sorted characters of S in previous operations) and also find S[L] ( the substring S[0…L-1] is sorted so we don’t have to do anything with it, S[R]will be placed at S[L+1]).
- After K operations, the lexicographically smallest possible string is obtained.
Illustration:
In the above illustration, since the first three characters of the original string were in sorted order we dont have to involve them in any operation Search that character which will appear after them in the sorted order, assume it appears at index R (the character will be S[R]) we select the index of character after the first three character as R (the character will be S[R]) Now we reverse the substring S[L…R] which will result in the character S[R] to appear at S[L+1] and now the first 4 characters ofthe string S are in sorted order
Below is the implementation of the above approach.
C++
// C++ code to implement the approach #include <bits/stdc++.h> using namespace std; // Function to return the lexicographically // minimum string after k operations string findStr(string s, int k) { // Sorted string string ss = s; sort(ss.begin(), ss.end()); // String after each operation string ans = "" ; for ( int i = 0; i < k; i++) { ans = "" ; int r = 0; int l = -1; for ( int i = 0; i < s.length(); i++) { for ( int j = 0; j < ss.length(); j++) { if (s[j] == ss[i] && i == j) { l = i; break ; } else if (s[j] == ss[i]) { r = j; break ; } } if (r > 0) // to avoid unnecessary checking break ; } // There is no group of sorted characters // in the beginning of the string S if (l == -1) { for ( int i = r; i >= 0; i--) ans.push_back(s[i]); for ( int i = r + 1; i < s.length(); i++) ans.push_back(s[i]); } // string S is already sorted or S = SS else if (l == s.length() - 1) { ans = s; } // Some part of string S in the beginning // is sorted else { for ( int i = 0; i <= l; i++) ans.push_back(s[i]); for ( int i = r; i > l; i--) ans.push_back(s[i]); for ( int i = r + 1; i < s.length(); i++) ans.push_back(s[i]); } // cout << "after " << i+1 << " operations // : " << ans << '\n'; use the above line of // code to see how S changes after every // operation s = ans; } return s; } // Driver Code int main() { // Number of operations int K = 3; // Given string string S = "fgazcbdfge" ; // Final answer string string ans = findStr(S, K); cout << ans; return 0; } |
Java
// Java code to implement the approach import java.util.*; class GFG { // Function to return the lexicographically // minimum string after k operations static String findStr(String s, int k) { // Sorted string String ss = s; char [] arr = ss.toCharArray(); Arrays.sort(arr); ss = new String(arr); // String after each operation String ans = "" ; for ( int a = 0 ; a < k; a++) { ans = "" ; int r = 0 ; int l = - 1 ; for ( int i = 0 ; i < s.length(); i++) { for ( int j = 0 ; j < ss.length(); j++) { if (s.charAt(j) == ss.charAt(i) && i == j) { l = i; break ; } else if (s.charAt(j) == ss.charAt(i)) { r = j; break ; } } if (r > 0 ) // to avoid unnecessary checking break ; } // There is no group of sorted characters // in the beginning of the string S if (l == - 1 ) { for ( int i = r; i >= 0 ; i--) ans += s.charAt(i); for ( int i = r + 1 ; i < s.length(); i++) ans += s.charAt(i); } // string S is already sorted or S = SS else if (l == s.length() - 1 ) { ans = s; } // Some part of string S in the beginning // is sorted else { for ( int i = 0 ; i <= l; i++) ans += s.charAt(i); for ( int i = r; i > l; i--) ans += s.charAt(i); for ( int i = r + 1 ; i < s.length(); i++) ans += s.charAt(i); } // cout << "after " << i+1 << " operations // : " << ans << '\n'; use the above line of // code to see how S changes after every // operation s = ans; } return s; } // Driver Code public static void main(String[] args) { // Number of operations int K = 3 ; // Given string String S = "fgazcbdfge" ; // Final answer string String ans = findStr(S, K); System.out.print(ans); } } // This code is contributed by ukasp. |
Python3
# python3 code to implement the approach # Function to return the lexicographically # minimum string after k operations def findStr(s, k): # Sorted string ss = list (s) ss.sort() # String after each operation ans = "" for i in range ( 0 , k): ans = "" r = 0 l = - 1 for i in range ( 0 , len (s)): for j in range ( 0 , len (ss)): if (s[j] = = ss[i] and i = = j): l = i break elif (s[j] = = ss[i]): r = j break if (r > 0 ): # to avoid unnecessary checking break # There is no group of sorted characters # in the beginning of the string S if (l = = - 1 ): for i in range (r, - 1 , - 1 ): ans + = s[i] for i in range (r + 1 , len (s)): ans + = s[i] # string S is already sorted or S = SS elif (l = = len (s) - 1 ): ans = s # Some part of string S in the beginning # is sorted else : for i in range ( 0 , l + 1 ): ans + = s[i] for i in range (r, l, - 1 ): ans + = s[i] for i in range (r + 1 , len (s)): ans + = s[i] # print(f"after {i+1} operations: {ans}") # use the above line of # code to see how S changes after every # operation s = ans return s # Driver Code if __name__ = = "__main__" : # Number of operations K = 3 # Given string S = "fgazcbdfge" # Final answer string ans = findStr(S, K) print (ans) # This code is contributed by rakeshsahni |
C#
// C# code to implement the approach using System; class GFG { // Function to return the lexicographically // minimum string after k operations static string findStr( string s, int k) { // Sorted string string ss = s; char [] arr = ss.ToCharArray(); Array.Sort(arr); ss = new string (arr); // String after each operation string ans = "" ; for ( int a = 0; a < k; a++) { ans = "" ; int r = 0; int l = -1; for ( int i = 0; i < s.Length; i++) { for ( int j = 0; j < ss.Length; j++) { if (s[j] == ss[i] && i == j) { l = i; break ; } else if (s[j] == ss[i]) { r = j; break ; } } if (r > 0) // to avoid unnecessary checking break ; } // There is no group of sorted characters // in the beginning of the string S if (l == -1) { for ( int i = r; i >= 0; i--) ans += s[i]; for ( int i = r + 1; i < s.Length; i++) ans += s[i]; } // string S is already sorted or S = SS else if (l == s.Length - 1) { ans = s; } // Some part of string S in the beginning // is sorted else { for ( int i = 0; i <= l; i++) ans += s[i]; for ( int i = r; i > l; i--) ans += s[i]; for ( int i = r + 1; i < s.Length; i++) ans += s[i]; } // cout << "after " << i+1 << " operations // : " << ans << '\n'; use the above line of // code to see how S changes after every // operation s = ans; } return s; } // Driver Code public static void Main() { // Number of operations int K = 3; // Given string string S = "fgazcbdfge" ; // Final answer string string ans = findStr(S, K); Console.Write(ans); } } // This code is contributed by Samim Hossain Mondal. |
Javascript
<script> // JavaScript code for the above approach // Function to return the lexicographically // minimum string after k operations function findStr(s, k) { // Sorted string let ss = s.split( '' ); ss.sort( function (a, b) { return a.charCodeAt(0) - b.charCodeAt(0) }) // String after each operation let ans = []; for (let i = 0; i < k; i++) { ans = []; let r = 0; let l = -1; for (let i = 0; i < s.length; i++) { for (let j = 0; j < ss.length; j++) { if (s[j] == ss[i] && i == j) { l = i; break ; } else if (s[j] == ss[i]) { r = j; break ; } } if (r > 0) // to avoid unnecessary checking break ; } // There is no group of sorted characters // in the beginning of the string S if (l == -1) { for (let i = r; i >= 0; i--) ans.push(s[i]); for (let i = r + 1; i < s.length; i++) ans.push(s[i]); } // string S is already sorted or S = SS else if (l == s.length - 1) { ans = s; } // Some part of string S in the beginning // is sorted else { for (let i = 0; i <= l; i++) ans.push(s[i]); for (let i = r; i > l; i--) ans.push(s[i]); for (let i = r + 1; i < s.length; i++) ans.push(s[i]); } // code to see how S changes after every // operation s = [...ans]; } return s.join( '' ); } // Driver Code // Number of operations let K = 3; // Given string let S = "fgazcbdfge" ; // Final answer string let ans = findStr(S, K); document.write(ans); // This code is contributed by Potta Lokesh </script> |
abcdgfzfge
Time Complexity: O(K * N2) where N is the length of the string
Auxiliary Space: O(1)
Please Login to comment...