Given a string S of length N and an array of queries A[] of size M, the task is to find the final string after performing M operations on the string. In each operation reverse a segment of the string S from position (A[i] to N-A[i]+1).
Examples:
Input: N = 6, S = “abcdef”, M = 3, A = {1, 2, 3}
Output: “fbdcea”
Explanation: After the first operation, the string will be “fedcba”.
After the second operation it will be “fbcdea”.
After the third operation the final string will be “fbdcea”.Input: N = 2, S = “jc”, M = 5, A = {1, 1, 1, 1, 1}
Output: “cj”
Naive Approach:
A simple solution is to update the string after each operation by reversing it for the given range as defined by the query.
Below is the implementation of the naive approach:
C++
// C++ program to find the string after // M reversals on query ranges #include <bits/stdc++.h> using namespace std; // Function for reversing string according // to each query void reverseForAll(string& S, int N, vector< int >& A, int M) { for ( int i = 0; i < M; i++) { int start = A[i] - 1; int end = N - A[i] + 1; reverse(S.begin() + start, S.begin() + end); } } // Driver Code int main() { int N = 6; string S = "abcdef" ; int M = 3; vector< int > A = { 1, 2, 3 }; // Function call reverseForAll(S, N, A, M); cout << S; return 0; } |
Java
// Java program to find the string after M reversals on // query ranges import java.io.*; class GFG { // Function for reversing string according // to each query public static String reverseForAll(String S, int N, int A[], int M) { String tmp = "" ; for ( int j = 0 ; j < M; j++) { int start = A[j] - 1 ; int end = N - A[j] + 1 ; tmp = "" ; // reverse(S.begin() + start, S.begin() + end); // string tmp=""; for ( int i = 0 ; i < start; i++) tmp += S.charAt(i); for ( int i = end - 1 ; i >= start; i--) tmp += S.charAt(i); for ( int i = end; i < S.length(); i++) tmp += S.charAt(i); S = tmp; } return tmp; } // Driver Code public static void main(String[] args) { int N = 6 ; String S = "abcdef" ; int M = 3 ; int A[] = { 1 , 2 , 3 }; // Function call String ans = reverseForAll(S, N, A, M); System.out.println(ans); } } // This code is contributed by Akshay // Tripathi(akshaytripathi19410) |
Python3
# Python program to find the string after # M reversals on query ranges # Function for reversing string according # to each query def reverseForAll( S, N, A, M): for i in range ( 0 ,M): start = A[i] - 1 ; end = N - A[i] + 1 ; S = S[:start] + "".join( reversed (S[start:end])) + S[end:]; return S; # Driver Code N = 6 ; S = "abcdef" ; M = 3 ; A = [ 1 , 2 , 3 ]; # Function call S = reverseForAll(S, N, A, M); print (S); |
C#
using System; using System.Collections.Generic; class GFG { // Function for reversing string according // to each query static string reverseForAll( string S, int N, List< int > A, int M) { string tmp= "" ; for ( int j = 0; j < M; j++) { int start = A[j] - 1; int end = N - A[j] + 1; tmp= "" ; //reverse(S.begin() + start, S.begin() + end); //string tmp=""; for ( int i=0; i<start; i++) tmp+=S[i]; for ( int i=end-1; i>=start; i--) tmp+=S[i]; for ( int i=end; i<S.Length; i++) tmp+=S[i]; S=tmp; } return tmp; } // Driver Code public static void Main() { int N = 6; string S = "abcdef" ; int M = 3; List< int > A = new List< int >(); A.Add(1); A.Add(2); A.Add(3); // Function call string ans=reverseForAll(S, N, A, M); Console.Write(ans); } } // This code is contributed by ratiagarwal. |
Javascript
// Javascript program to find the string after // M reversals on query ranges // Function for reversing string according // to each query function reverseForAll(S, N, A, M) { for (let i = 0; i < M; i++) { let start = A[i] - 1; let end = N - A[i] + 1; let sub = S.substring(start, end); sub = sub.split( "" ).reverse().join( "" ); S = S.substring(0, start) + sub + S.substring(end); } document.write(S); } // Driver Code let N = 6; let S = "abcdef" ; let M = 3; let A = [ 1, 2, 3 ]; // Function call reverseForAll(S, N, A, M); |
fbdcea
Time Complexity: O(M*N)
Auxiliary Space: O(1)
Efficient Approach: Please check out the Difference Array | Range update query in O(1) article before reading this approach.
Observations:
Notice that when the same section of a string is reversed twice it gains back its original state.
As in the example:
Consider (1-based Indexing) that:
- The first reversal is to be applied to the range [1, 6].
- The second reversal is to be applied to the range [2, 5].
- The third reversal is to be applied to the range [3, 4].
It can be observed that:
- reversal is applied on 1 and 6 indices one time.
- reversal is applied on 2 and 5 indices two times.
- reversal is applied on 3 and 4 indices three times.
In the final string, characters on indices 2 and 5 remained unchanged while indices 1, 3, 4, and 6 are reversed. So, the indices on which reversal is to be applied an even number of times do not take part in the final reversal of string while those with odd no. of reversal queries take part in reversal.
So, the idea of the efficient approach to solve this problem is:
Count for each index, how many queries include this number, if the index is included in even number of queries, it would not be reversed, otherwise if the index is included in odd number of queries it would be reversed.
Follow the steps to solve this problem:
- Take a count array initialized to 0 with a length equal to the length of the string. This will count how many reversal queries include the corresponding index.
- For each query, increment all the values in the range where reversal should be done.
- This increment can be done in O(1) using the concept mentioned in the Difference Array | Range update query in O(1) article.
- Take an empty string and traverse the count array.
- Count array is traversed and for the indices with even value, characters at those indices from the original string are added to the answer string, otherwise, characters from the reversed string are added.
Below is the implementation of the efficient approach:
C++
// C++ program to find the string after // M reversals on query ranges #include <bits/stdc++.h> using namespace std; // Increments the value at first index and // decrements at next of last index void updateRange(vector< int >& count, int i, int j) { count[i]++; // Check index out of bound if (j + 1 < count.size()) count[j + 1]--; } // Prefix sum to finalise count value // at each index void finaliseCountArray(vector< int >& count) { for ( int i = 0; i < count.size(); i++) count[i] += count[i - 1]; } // Function for reversing string according // to each query string reverseForAll(string S, int N, vector< int >& A, int M) { vector< int > count(N, 0); // Traversal of query array for ( int i = 0; i < M; i++) { int start = A[i] <= (N + 1) / 2 ? A[i] - 1 : N - A[i]; int end = A[i] <= (N + 1) / 2 ? N - A[i] : A[i] - 1; // Increment the value of all indices // between both indices updateRange(count, start, end); } // Finalising count array using prefix sum finaliseCountArray(count); // Storing the characters at indices with // odd no. of reversal queries in reverse // manner, this stores the required indices // to string temp as well as temp is // reversed at the same time string temp; for ( int i = count.size() - 1; i >= 0; i--) { if (count[i] % 2 != 0) temp.push_back(S[i]); } // Storing the new characters in // original string int i = 0, j = 0; for (i = 0; i < count.size(); i++) { // For characters with odd reversal // queries character is taken from // string temp if (count[i] % 2 != 0) S[i] = temp[j++]; // If count is even then there is no // need to update characters as those // characters do not take part // in reversal } // Return final string return S; } // Driver Code int main() { int N = 6; string S = "abcdef" ; int M = 3; vector< int > A = { 1, 2, 3 }; // Function call cout << reverseForAll(S, N, A, M); return 0; } |
Java
/*package whatever //do not write package name here */ // Java program to find the string after // M reversals on query ranges import java.io.*; class GFG { // Increments the value at first index and // decrements at next of last index static void updateRange( int [] count, int i, int j) { count[i]++; // Check index out of bound if (j + 1 < count.length) count[j + 1 ]--; } // Prefix sum to finalise count value // at each index static void finaliseCountArray( int [] count) { for ( int i = 1 ; i < count.length; i++) count[i] += count[i - 1 ]; } // Function for reversing string according // to each query static String reverseForAll(String S, int N, int [] A, int M){ int [] count = new int [N]; char str[] = S.toCharArray(); // Traversal of query array for ( int i = 0 ; i < M; i++) { int start = A[i] <= (N + 1 ) / 2 ? A[i] - 1 : N - A[i]; int end = A[i] <= (N + 1 ) / 2 ? N - A[i] : A[i] - 1 ; // Increment the value of all indices // between both indices updateRange(count, start, end); } // Finalising count array using prefix sum finaliseCountArray(count); // Storing the characters at indices with // odd no. of reversal queries in reverse // manner, this stores the required indices // to string temp as well as temp is // reversed at the same time String temp = "" ; for ( int i = count.length - 1 ; i >= 0 ; i--) { if (count[i] % 2 != 0 ) temp += S.charAt(i); } // Storing the new characters in // original string int j = 0 ; for ( int i = 0 ; i < count.length; i++) { // For characters with odd reversal // queries character is taken from // string temp if (count[i] % 2 != 0 ) str[i] = temp.charAt(j++); // If count is even then there is no // need to update characters as those // characters do not take part // in reversal } // Return final string return new String(str); } public static void main (String[] args) { int N = 6 ; String S = "abcdef" ; int M = 3 ; int [] A = { 1 , 2 , 3 }; System.out.println(reverseForAll(S, N, A, M)); } } // This code is contributed by aadityapburujwale |
Python3
class GFG : # Increments the value at first index and # decrements at next of last index @staticmethod def updateRange( count, i, j) : count[i] + = 1 # Check index out of bound if (j + 1 < len (count)) : count[j + 1 ] - = 1 # Prefix sum to finalise count value # at each index @staticmethod def finaliseCountArray( count) : i = 1 while (i < len (count)) : count[i] + = count[i - 1 ] i + = 1 # Function for reversing string according # to each query @staticmethod def reverseForAll( S, N, A, M) : count = [ 0 ] * (N) str = list (S) # Traversal of query array i = 0 while (i < M) : start = A[i] - 1 if A[i] < = int ((N + 1 ) / 2 ) else N - A[i] end = N - A[i] if A[i] < = int ((N + 1 ) / 2 ) else A[i] - 1 # Increment the value of all indices # between both indices GFG.updateRange(count, start, end) i + = 1 # Finalising count array using prefix sum GFG.finaliseCountArray(count) # Storing the characters at indices with # odd no. of reversal queries in reverse # manner, this stores the required indices # to string temp as well as temp is # reversed at the same time temp = "" i = len (count) - 1 while (i > = 0 ) : if (count[i] % 2 ! = 0 ) : temp + = S[i] i - = 1 # Storing the new characters in # original string j = 0 i = 0 while (i < len (count)) : # For characters with odd reversal # queries character is taken from # string temp if (count[i] % 2 ! = 0 ) : j = j + 1 str [i] = temp[j - 1 ] i + = 1 # Return final string return ''.join( str ) @staticmethod def main( args) : N = 6 S = "abcdef" M = 3 A = [ 1 , 2 , 3 ] print (GFG.reverseForAll(S, N, A, M)) if __name__ = = "__main__" : GFG.main([]) # This code is contributed by aadityaburujwale. |
C#
// Include namespace system // C# program to find the string after // M reversals on query ranges using System; public class GFG { // Increments the value at first index and // decrements at next of last index public static void updateRange( int [] count, int i, int j) { count[i]++; // Check index out of bound if (j + 1 < count.Length) { count[j + 1]--; } } // Prefix sum to finalise count value // at each index public static void finaliseCountArray( int [] count) { for ( int i = 1; i < count.Length; i++) { count[i] += count[i - 1]; } } // Function for reversing string according // to each query public static String reverseForAll(String S, int N, int [] A, int M) { int [] count = new int [N]; char [] str = S.ToCharArray(); // Traversal of query array for ( int i = 0; i < M; i++) { var start = A[i] <= ( int )((N + 1) / 2) ? A[i] - 1 : N - A[i]; var end = A[i] <= ( int )((N + 1) / 2) ? N - A[i] : A[i] - 1; // Increment the value of all indices // between both indices GFG.updateRange(count, start, end); } // Finalising count array using prefix sum GFG.finaliseCountArray(count); // Storing the characters at indices with // odd no. of reversal queries in reverse // manner, this stores the required indices // to string temp as well as temp is // reversed at the same time var temp = "" ; for ( int i = count.Length - 1; i >= 0; i--) { if (count[i] % 2 != 0) { temp += S[i]; } } // Storing the new characters in // original string var j = 0; for ( int i = 0; i < count.Length; i++) { // For characters with odd reversal // queries character is taken from // string temp if (count[i] % 2 != 0) { str[i] = temp[j++]; } } // Return final string return new String(str); } public static void Main(String[] args) { var N = 6; var S = "abcdef" ; var M = 3; int [] A = {1, 2, 3}; Console.WriteLine(GFG.reverseForAll(S, N, A, M)); } } // This code is contributed by aadityapburujwale |
Javascript
// Function for updating the count array function updateRange(count, i, j) { count[i] += 1; if (j + 1 < count.length) { count[j + 1] -= 1; } } // Function for finalizing the count array function finalizeCountArray(count) { for (let i = 1; i < count.length; i++) { count[i] += count[i - 1]; } } // Function for reversing the string according to each query function reverseForAll(S, N, A, M) { let count = new Array(N).fill(0); let str = S.split( '' ); // Traversal of query array for (let i = 0; i < M; i++) { let start = A[i] <= Math.ceil((N + 1) / 2) ? A[i] - 1 : N - A[i]; let end = A[i] <= Math.ceil((N + 1) / 2) ? N - A[i] : A[i] - 1; // Increment the value of all indices between both indices updateRange(count, start, end); } // Finalizing count array using prefix sum finalizeCountArray(count); // Storing the characters at indices with odd no. of reversal queries in reverse manner // this stores the required indices to string temp as well as temp is reversed at the same time let temp = "" ; for (let i = count.length - 1; i >= 0; i--) { if (count[i] % 2 !== 0) { temp += S[i]; } } // Storing the new characters in original string let j = 0; for (let i = 0; i < count.length; i++) { // For characters with odd reversal queries character is taken from string temp if (count[i] % 2 !== 0) { j++; str[i] = temp[j - 1]; } } // Return final string return str.join( '' ); } let N = 6; let S = "abcdef" ; let M = 3; let A = [1, 2, 3]; document.write(reverseForAll(S, N, A, M)); //This code is contributed by ik_9 |
fbdcea
Time Complexity: O(M+N)
Auxiliary Space: O(N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!