An in-place algorithm for String Transformation

Given a string, move all even positioned elements to end of string. While moving elements, keep the relative order of all even positioned and odd positioned elements same. For example, if the given string is “a1b2c3d4e5f6g7h8i9j1k2l3m4″, convert it to “abcdefghijklm1234567891234″ in-place and in O(n) time complexity.

Below are the steps:

1. Cut out the largest prefix sub-string of size of the form 3^k + 1. In this step, we find the largest non-negative integer k such that 3^k+1 is smaller than or equal to n (length of string)

2. Apply cycle leader iteration algorithm ( it has been discussed below ), starting with index 1, 3, 9…… to this sub-string. Cycle leader iteration algorithm moves all the items of this sub-string to their correct positions, i.e. all the alphabets are shifted to the left half of the sub-string and all the digits are shifted to the right half of this sub-string.

3. Process the remaining sub-string recursively using steps#1 and #2.

4. Now, we only need to join the processed sub-strings together. Start from any end ( say from left ), pick two sub-strings and apply the below steps:

….4.1 Reverse the second half of first sub-string.
….4.2 Reverse the first half of second sub-string.
….4.3 Reverse the second half of first sub-string and first half of second sub-string together.

5. Repeat step#4 until all sub-strings are joined. It is similar to k-way merging where first sub-string is joined with second. The resultant is merged with third and so on.

Let us understand it with an example:

Please note that we have used values like 10, 11 12 in the below example. Consider these values as single characters only. These values are used for better readability.

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
a 1 b 2 c 3 d 4 e 5 f  6  g  7  h  8  i  9  j  10 k  11 l  12 m  13

After breaking into size of the form 3^k + 1, two sub-strings are formed of size 10 each. The third sub-string is formed of size 4 and the fourth sub-string is formed of size 2.

0 1 2 3 4 5 6 7 8 9         
a 1 b 2 c 3 d 4 e 5         

10 11 12 13 14 15 16 17 18 19          
f  6  g  7  h  8  i  9  j  10           

20 21 22 23 
k  11 l  12 

24 25
m  13

After applying cycle leader iteration algorithm to first sub-string:

0 1 2 3 4 5 6 7 8 9          
a b c d e 1 2 3 4 5          

10 11 12 13 14 15 16 17 18 19          
f  6  g  7  h  8  i  9  j  10 

20 21 22 23 
k  11 l  12 

24 25
m  13

After applying cycle leader iteration algorithm to second sub-string:

0 1 2 3 4 5 6 7 8 9          
a b c d e 1 2 3 4 5          

10 11 12 13 14 15 16 17 18 19           
f  g  h  i  j  6  7  8  9  10 

20 21 22 23 
k  11 l  12 

24 25
m 13

After applying cycle leader iteration algorithm to third sub-string:

0 1 2 3 4 5 6 7 8 9          
a b c d e 1 2 3 4 5          

10 11 12 13 14 15 16 17 18 19            
f  g  h  i  j  6  7  8  9  10

20 21 22 23 
k  l  11 12 

24 25
m  13

After applying cycle leader iteration algorithm to fourth sub-string:

0 1 2 3 4 5 6 7 8 9  
a b c d e 1 2 3 4 5  

10 11 12 13 14 15 16 17 18 19             
f  g  h  i  j  6  7  8  9  10   

20 21 22 23 
k  l  11 12 

24 25
m  13



Joining first sub-string and second sub-string:
1. Second half of first sub-string and first half of second sub-string reversed.

0 1 2 3 4 5 6 7 8 9          
a b c d e 5 4 3 2 1            <--------- First Sub-string  

10 11 12 13 14 15 16 17 18 19             
j  i  h  g  f  6  7  8  9  10  <--------- Second Sub-string  

20 21 22 23 
k  l  11 12 

24 25
m  13

2. Second half of first sub-string and first half of second sub-string reversed together( They are merged, i.e. there are only three sub-strings now ).

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
a b c d e f g h i j 1  2  3  4  5  6  7  8  9  10

20 21 22 23 
k  l  11 12 

24 25
m  13



Joining first sub-string and second sub-string:
1. Second half of first sub-string and first half of second sub-string reversed.

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
a b c d e f g h i j 10 9  8  7  6  5  4  3  2  1 <--------- First Sub-string  

20 21 22 23 
l  k  11 12                                      <--------- Second Sub-string

24 25
m  13

2. Second half of first sub-string and first half of second sub-string reversed together( They are merged, i.e. there are only two sub-strings now ).

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23  
a b c d e f g h i j k  l  1  2  3  4  5  6  7  8  9  10 11 12  

24 25
m  13 



Joining first sub-string and second sub-string:
1. Second half of first sub-string and first half of second sub-string reversed.

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 
a b c d e f g h i j k  l  12 11 10 9  8  7  6  5  4  3  2  1 <----- First Sub-string

24 25
m  13   <----- Second Sub-string 

2. Second half of first sub-string and first half of second sub-string reversed together( They are merged, i.e. there is only one sub-string now ).

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
a b c d e f g h i j k  l  m  1  2  3  4  5  6  7  8  9  10 11 12 13

Since all sub-strings have been joined together, we are done.



How does cycle leader iteration algorithm work?

Let us understand it with an example:

Input:
0 1 2 3 4 5 6 7 8 9
a 1 b 2 c 3 d 4 e 5

Output:
0 1 2 3 4 5 6 7 8 9 
a b c d e 1 2 3 4 5

Old index    New index
0		0
1		5
2		1
3		6
4		2
5		7
6		3
7		8
8		4
9		9

Let len be the length of the string. If we observe carefully, we find that the new index is given by below formula:

if( oldIndex is odd )
	newIndex = len / 2 + oldIndex / 2;
else
        newIndex = oldIndex / 2;

So, the problem reduces to shifting the elements to new indexes based on the above formula.

Cycle leader iteration algorithm will be applied starting from the indices of the form 3^k, starting with k = 0.

Below are the steps:

1. Find new position for item at position i. Before putting this item at new position, keep the back-up of element at new position. Now, put the item at new position.

2. Repeat step#1 for new position until a cycle is completed, i.e. until the procedure comes back to the starting position.

3. Apply cycle leader iteration algorithm to the next index of the form 3^k. Repeat this step until 3^k < len.

Consider input array of size 28:

The first cycle leader iteration, starting with index 1:

1->14->7->17->22->11->19->23->25->26->13->20->10->5->16->8->4->2->1

The second cycle leader iteration, starting with index 3:

3->15->21->24->12->6->3

The third cycle leader iteration, starting with index 9:

9->18->9

Based on the above algorithm, below is the code:

#include <stdio.h>
#include <string.h>
#include <math.h>

// A utility function to swap characters
void swap ( char* a, char* b )
{
    char t = *a;
    *a = *b;
    *b = t;
}

// A utility function to reverse string str[low..high]
void reverse ( char* str, int low, int high )
{
    while ( low < high )
    {
        swap( &str[low], &str[high] );
        ++low;
        --high;
    }
}

// Cycle leader algorithm to move all even positioned elements
// at the end.
void cycleLeader ( char* str, int shift, int len )
{
    int j;
    char item;

    for (int i = 1; i < len; i *= 3 )
    {
        j = i;

        item = str[j + shift];
        do
        {
            // odd index
            if ( j & 1 )
                j = len / 2 + j / 2;
            // even index
            else
                j /= 2;

            // keep the back-up of element at new position
            swap (&str[j + shift], &item);
        }
        while ( j != i );
    }
}

// The main function to transform a string. This function mainly uses
// cycleLeader() to transform
void moveNumberToSecondHalf( char* str )
{
    int k, lenFirst;

    int lenRemaining = strlen( str );
    int shift = 0;

    while ( lenRemaining )
    {
        k = 0;

        // Step 1: Find the largest prefix subarray of the form 3^k + 1
        while ( pow( 3, k ) + 1 <= lenRemaining )
            k++;
        lenFirst = pow( 3, k - 1 ) + 1;
        lenRemaining -= lenFirst;

        // Step 2: Apply cycle leader algorithm for the largest subarrau
        cycleLeader ( str, shift, lenFirst );

        // Step 4.1: Reverse the second half of first subarray
        reverse ( str, shift / 2, shift - 1 );

        // Step 4.2: Reverse the first half of second sub-string.
        reverse ( str, shift, shift + lenFirst / 2 - 1 );

        // Step 4.3 Reverse the second half of first sub-string and first
        // half of second sub-string together
        reverse ( str, shift / 2, shift + lenFirst / 2 - 1 );

        // Increase the length of first subarray
        shift += lenFirst;
    }
}

// Driver program to test above function
int main()
{
    char str[] = "a1b2c3d4e5f6g7";
    moveNumberToSecondHalf( str );
    printf( "%s", str );
    return 0;
}

Click here to see various test cases.

Notes:
1. If the array size is already in the form 3^k + 1, We can directly apply cycle leader iteration algorithm. There is no need of joining.

2. Cycle leader iteration algorithm is only applicable to arrays of size of the form 3^k + 1.

How is the time complexity O(n) ?
Each item in a cycle is shifted at most once. Thus time complexity of the cycle leader algorithm is O(n). The time complexity of the reverse operation is O(n). We will soon update the mathematical proof of the time complexity of the algorithm.

Exercise:
Given string in the form “abcdefg1234567″, convert it to “a1b2c3d4e5f6g7″ in-place and in O(n) time complexity.

References:
A Simple In-Place Algorithm for In-Shu?e.

__Aashish Barnwal.Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.





  • Teegan.

    The algo in the paper is actualy different, which affects the time complexity. You need to do the three reverses first, and then do the cycle leader for the first part etc.

    • Careegan

      Yes, as given the algorithm is not O(n). It is possibly Omega(n logn).

      • Careegan

        (The paper has it right, though)

  • Saurabh

    Since the input to be segregated is a String like “a5b6c7d8″ we can use String’s substring method to handpick numbers from the string and append them at the end of the string in a single for loop.

    Time complexity: O(n)
    space complexity: O(1)

    Example:

    i here denotes the index of the character in the string

    i=1 — input: a5b6c7d8 (Append 5 to the end of string) output: ab6c7d85
    i=2 — input: ab6c7d85 (Append 6 to the end of string) output: abc7d856
    i=3 — input: abc7d856 (Append 7 to the end of string) output: abcd8567
    i=4 — input: abcd8567 (Append 8 to the end of string) output: abcd5678

    Java Code is:
    public class SegregateCharAndNumbers {
    private static String input=”a5b6c7d8″;

    public static void main(String[] args) {
    System.out.println(“String before change = ” + input);

    for(int i=1; i<input.length()/2+1;i++) {
    input = input.substring(0,i) + input.substring(i+1, input.length()) + input.charAt(i);
    }
    System.out.println("String after Input = " + input);
    }
    }

    • Saurabh

      Code was not saved correctly. Here is the link for ideone

      https://ideone.com/TDq0Wj

      • Pavi.8081

        Good try Saurabh.
        But what you have suggested is not inplace.
        Thats because you are using method substring, which creates new string everytime. Am I right?

        • Saurabh

          ah ha .. you are right .. how can I miss that … humm .. even if we try stringBuilder and try something like this, SB.subString would still create new string internally … got it .. thanks for pointing it out :)

          String temp = null;
          for(int i=1; i<inputBuilder.length()/2+1;i++) {
          temp = inputBuilder.substring(0,i) + inputBuilder.substring(i+1, inputBuilder.length()) + inputBuilder.charAt(i);
          inputBuilder.delete(0, inputBuilder.length());
          inputBuilder.append(temp);
          }

  • cinderilla

    Why would cycle leader algorithm only apply to the array with size of 3^k+1?

  • Ambu Sreedharan

    void stringSeperate(string& A){

    if(A.length() < 3) return;

    for(int i = 0, j = 0; i=j+1; m–){

    A[m+1] = A[m];

    }

    if(j<i)A[j+1] = temp;

    cout<<A<<"n";

    }

    }

  • wgpshashank

    Just played this , you can modified below to get desired result https://ideone.com/NBxoRL

  • trying
  • skrauniyar

    I am wondering that why we need to do all these stuff. we can directly get the result by applying cycle leader iteration algorithm. here I have pasted my code, and for simplicity I have initialized the string. please correct me if I am wrong or any possible changes..

    #include
    #include
    #include
    using namespace std;

    int main()
    {
    char str[]=”a1b2c3d4e5f6g7h8i9j0k”;
    char opstr[sizeof(str) + 1]; //opstr is output char array
    int length=strlen(str);
    int i;
    if(length%2==0){ //if string length is even
    for(i=0;i<length;i++) {
    if(i%2==0) {
    opstr[i/2]=str[i];
    }
    else {
    opstr[i/2+length/2]=str[i];
    }
    }
    }
    else { // if string length is odd
    for(i=0;i<length;i++) {
    if(i%2==0) {
    opstr[i/2]=str[i];
    }
    else {
    opstr[i/2+length/2+1]=str[i];
    }
    }
    }
    opstr[i]='';
    cout<<opstr;
    return 0;
    }

  • raj
     
    void trans1(char *str)
    {
        int n=strlen(str);
        int al=0;
        int num=(n/2);
        int next=num+1;
        int c=0;
        while(num<n)
        {
            char temp;
            temp=str[num];
            str[num]=str[num-1];
            str[num-1]=temp;
            num--;
            c++;
            if(num==al)
            {
                num=next;
                al++;
                next++;
            }
        }
       printf("\n%s",str) ;
       printf("\n%d",c);
    }
    
     

    I/P:abcdefghijklm1234567891234
    o/p:1234567891234abcdefghijklm

  • raj
     
    /* Paste your code here (You may delete these lines if not writing code) */
    void trans(char *str)
    {
        int al=2;
        int num=1;
        int next=4;
        int n=strlen(str);
        while(al>num && al<n)
        {
            char temp;
            temp=str[al-1];
            str[al-1]=str[al];
            str[al]=temp;
            al--;
            if(al==num)
            {al=next;
            next=next+2;
            num++;
            }
         }
        printf("%s\n",str);
       }
    
     

    I dont know the complexity of this code .. think its O(nlogn)??

  • gargsanjay

    dont u think we first apply cycle leader theorem on the remaining array and den do the reverse thing??
    reverse is done just after cycle applied on first subarray.

     
    /* Paste your code here (You may delete these lines if not writing code) */
     
  • abhishek08aug

    Intelligent 😀

  • stranger

    The above code is not O(n). It takes (logn-1)*n/4. So, time complexity is O(nlogn).

    • kartik

      @stranger: Thanks for inputs. We will check it. Could you please let us know how did you get (logn-1)*n/4?

  • sabawat

    #include
    #include
    #include

    void fun(char *str);

    int main ()
    {

    char str[]=”S1A2B3A4W5A6T7″;

    printf(“Original string %s\n”, str);
    fun(str);
    printf(“Transformed string %s\n”, str);
    return 0;
    }

    void fun (char *str)
    {
    int i = 0, j, beg = 0, len;
    char temp;

    len = strlen(str);
    j = len – 1;

    if (len % 2 == 1)
    j += 1;

    while (beg < j){ i = ++beg; j–; while (i < j){ temp = str[i+1]; str[i+1] = str[i]; str[i] = temp; i++; i++; } } return; } OUTPUT: Original string S1A2B3A4W5A6T7 Transformed string SABAWAT1234567

    • tausif akram

      space is not o(1)

  • Niraj

    I have one solution , can you guys think about this solution ???

    <<<<<<<<<<<<<<<<<<<

    take 2nd element into temp variable and shift all elements one left and put temp variable at the last position . now increase the value i and do the same procedure for all i <= n/2 .

    Example ..

    a1b2c3d4e5 , temp = 1 , i=1

    ab2c3d4e51 , temp =2 , i=2
    abc3d4e512 , temp=3 , i=3
    abcd4e5123 ,temp = 4 , i=4
    abcde51234 , temp =5, i=5
    abcde12345

    while(i<= n/2 )
    {
    temp=str[i];
    j=i;
    while(j<n-1)
    str[j]=str[j+1];

    str[j]=temp;
    i++;

    }
    /* Paste your code here (You may delete these lines if not writing code) */

    • http://www.facebook.com/barnwal.aashish Aashish

      It seems there are some issues with your logic/code snippet. Can you post the complete code?
      See here.
      It spins infinitely. Also the complexity seems to be O(n^2).

      • Niraj

        #include

        int main()
        {
        int i, j, n;
        char temp;
        char str[] = “a1b2c3d4e567″;//”abcdefghijklm1234567891234″;

        n = strlen(str);
        i = 1;
        while(i <= n/2 )
        {
        temp = str[i];
        j = i;
        while(j<n-1) {
        str[j] = str[j+1];
        j++;
        }
        str[j] = temp;
        i++;

        }

        printf("%s", str);

        return 0;
        }

        o/p=abcde6123457

        You were missing one thing , J has to be increased .

        True its taking O(n^2) but very simple to understand and better to implement .

        @Ashish if you want me any clarification please let me know .

        /* Paste your code here (You may delete these lines if not writing code) */

        • Niraj

          if you have string like abcdef123456 and you need to convert it into form like a1b2c3d4e5f6 .

          then this algo will give correct result with time complexity O(n^2) .

          #include
          #include
          int main()
          {
          char a[]=”abcdefgh12345678″ ,temp ;
          int i,n,j,k;

          n=strlen(a);
          i=1;
          j=n/2;
          while(ii) {
          a[k]=a[k-1];
          k–;
          }
          a[k]=temp;
          i=i+2;
          j=j+1;
          }

          printf(“%s”,a);

          return 0;
          }

           
          /* Paste your code here (You may delete these lines if not writing code) */
           
        • http://www.facebook.com/barnwal.aashish Aashish

          The first solution seems to be working. We will look into this further. However the in-place algorithm is interesting. We will suggest you to go through it once. You will learn many things.
          The second solution to convert “abcdef123456″ to “a1b2c3d4e5f6″ is missing the outer loop.

          • Niraj

            I have for one very good in place solution in O(N) , i will share that solution to you very soon .

            I am pasting the second solution for converting “abcdef123456″ to “a1b2c3d4e5f6″ .
            i think it will give correct result .

            @Ashish are youtalking about the solution which you have given ????

            #include
            #include
            int main()
            {
            char a[]=”abcdefghi1234567810″ ,temp ;
            int i,n,j,k;

            n=strlen(a);
            i=1;
            j=n/2;

            while(ii) {
            a[k]=a[k-1];
            k–;
            }
            a[k]=temp;
            i=i+2;
            j=j+1;
            }

            printf(“%s”,a);

            return 0;

            }

             
            /* Paste your code here (You may delete these lines if not writing code) */
             
    • teng

      this is definitely O(N^2) in worst case….you need to shift the whole array whenever you discover an integer at position i that you need to put it at the end of the array, and shift all N – i items

  • pranav

    public String splitEvenOdd(String word)
    {
    int tempLength=word.length()-1;
    int flag=0;

    for(int i=0;i<=tempLength;i++)
    {

    if((i+1)%2==0 && flag==0)
    {
    word=word+word.charAt(i);
    word=word.substring(0, i)+word.substring(i+1,word.length());
    tempLength=tempLength-1;
    flag=1;
    }
    else if(i%2==0 && flag==1)
    {
    word=word+word.charAt(i);
    word=word.substring(0, i)+word.substring(i+1,word.length());
    tempLength=tempLength-1;
    flag=0;
    }

    }
    return word;
    }

  • ravi

    o(n/2) solution…why you all moving to complex.correct me if i am wrong.

     
    /* #include<stdio.h>
    #include<conio.h>
    #include<string.h>
    int main()
    {
        int n,i;
        char a[100],b[100],c[100];
        scanf("%s",&a);
        for(i=0;i<strlen(a)-1;i+=2)
        {
            b[i/2]=a[i];
            c[i/2]=a[i+1];
            }
            b[i/2]=c[i/2] = '\0';
            for(i=0;b[i]!='\0';i++)
            printf("%c",b[i]);
                for(i=0;c[i]!='\0';i++)
            printf("%c",c[i]);
            getch();
            return 0;
            }              
    */
     
    • Kartik

      @ravi: Please note the word “in-place” in title.

  • ravi

    O(N/2) Solution…..Why you all moving so complex??

    #include
    #include
    #include
    int main()
    {
    int n,i;
    char a[100],b[100],c[100];
    scanf(“%s”,&a);
    for(i=0;i<strlen(a)-1;i+=2)
    {
    b[i/2]=a[i];
    c[i/2]=a[i+1];
    }
    b[i/2]=c[i/2] = '';
    for(i=0;b[i]!='';i++)
    printf("%c",b[i]);
    for(i=0;c[i]!='';i++)
    printf("%c",c[i]);
    getch();
    return 0;
    }

  • Pavan

    In the program posted, the line lenFirst = pow( 3, k – 1 ) + 1;
    in the void moveNumberToSecondHalf( char* str ); function should be modified to lenFirst = pow( 3, k ) + 1;

    • Ankit

      First read the code carefully.
      “while loop” just above the line you mentioned will be terminated with an increment in the value of k from the required value…that’s why it is used pow(3,k-1) in next line.

  • Pavan

    In the program posted, the line lenFirst = pow( 3, k – 1 ) + 1; in
    the function void moveNumberToSecondHalf( char* str ); should be modified to lenFirst = pow( 3, k ) + 1;.

     
    /* Paste your code here (You may delete these lines if not writing code) */
     
  • Amature

    #include
    #include
    #include
    int main()
    {
    char c[]=”a1b2c3d4e5f6g7h8i9j1k2l3m4″;
    int n=1;
    int i=0,j=0,ind=0;
    while(ind<strlen(c)-2)
    {
    ind+=2;
    char tmp=c[ind];
    j=ind;
    for(i=0;i<n;i++)
    {
    c[j]=c[j-1];
    j–;
    }
    c[j]=tmp;
    n++;
    }
    printf("%s",c);
    }

    • tausif akram

      time o(n^2)

  • http://www.geeksforgeeks.org/forum/profile/arunkindra Arun

    #include
    void change_array(char *arr,int i);
    int main()
    {
    char str[]=”A1B2C3D4E5G6H7″;
    int len = strlen(str);
    int i;
    change_array(str,len);
    for(i=0;i<len;i++)
    printf("%c\t",str[i]);
    getchar();
    }
    int get_index(int id, int N,int m)
    {
    return ((id / m)+(id % m)*N );
    }

    void change_array( char *s, int len)
    {
    int N = len/(len/2);
    char temp;
    int i;
    for(i = 0; i < len; i++)
    {

    int new_id = get_index(i, N,len/2);
    while(new_id < i)
    {
    new_id = get_index(new_id, N,len/2);
    }

    temp = s[i];
    s[i] = s[new_id];
    s[new_id] = temp;
    }
    }

  • Nithya

    I agree with @anon. This problem can be realised as a problem of transposing a matrix of size order mxn where m=(length of string)/2 and n=2.If the length of the string is odd, we can add another character like ‘0’ to the end and do the transpose

     
    /* Paste your code here (You may delete these lines if not writing code) */
     
    • Venki

      Cool :) Here is working code, I didn’t realize this,

       
      #include <iostream>
      #include <bitset>
      using namespace std;
       
      typedef char data_t;
       
      void Print2DArray(char A[], int nr, int nc) {
          for(int r = 0; r < nr; r++) {
              for(int c = 0; c < nc; c++)
                  printf("%4c", *(A + r*nc + c));
       
              printf("\n");
          }
       
          printf("\n");
      }
       
      void MatrixTransposeInplaceArrangement(data_t A[], int r, int c) {
          int size = r*c - 1;
          data_t t;       // holds element to be replaced, eventually becomes next element to move
          int next;       // location of 't' to be moved
          int cycleBegin; // holds start of cycle
          int i;          // iterator
          bitset<128> b;  // hash to mark moved elements
       
          b.reset();
          b[0] = b[size] = 1;
          i = 1;          // Note that A[0] and A[size-1] won't move
          while( i < size ) {
              cycleBegin = i;
              t = A[i];
              do {
                  // Input  matrix [r x c]
                  // Output matrix 
                  // i_new = (i*r)%size
                  next = (i*r)%size;
                  swap<data_t>(A[next], t);
                  b[i] = 1;
                  i = next;
              } while( i != cycleBegin );
       
              // Get Next Move (what about querying random location?)
              for(i = 1; i < size && b[i]; i++)
                  ;
              cout << endl;
          }
      }
       
      void Fill(data_t buf[], int size) {
          // Fill abcd ...
          for(int i = 0; i < size; i++)
              buf[i] = 'a'+i;
       
          // Fill 0123 ...
          buf += size;
          for(int i = 0; i < size; i++)
              buf[i] = '0'+i;
      }
       
      void TestCase_01(void) {
          int r = 2, c = 10;
          int size = r*c;
          data_t *A = new data_t[size];
       
          Fill(A, c);
       
          Print2DArray(A, r, c), cout << endl;
          MatrixTransposeInplaceArrangement(A, r, c);
          Print2DArray(A, c, r), cout << endl;
       
          delete[] A;
      }
       
      int main() {
          TestCase_01();
       
          return 0;
      }
       

      Here is another excellent implementation (based on recursion) of similar problem by Sambasiva,

      http://effprog.blogspot.in/2010/08/in-given-array-of-elements-like-a1-a2.html

      Link to my original post (Inplace M x N size matrix transpose),

      http://www.geeksforgeeks.org/archives/25635

  • Sandy

    Can you please explain me the time complexity of this algo?

    You have claimed each element is shifted atmost once.

    But, i think they are getting shifted more than once.

    1. while applying the cycle leadership algo for each sub-string
    2. For reversing the second half and first half and soon
    3. Again reversing, while merging the both sub-strings.

    Please share your thoughts on this.

  • PsychoCoder
     
    At max (3/2)n operations are performed.
    
    It may stop while performing in-place operations, so for then the outer while (1) loop is there.
    It will stop when the alphabets are placed completely. It means that all elements are in proper position!
    
    
    void changeStringa1b2c3d4Toabcd1234(char str[], int size) {
      int mid = size>>1 ;
      int inext = mid - 1, restartIndex = 1;
      char ctemp = str[inext];
      while (1) {
        do {
          if ( ctemp >= 'a' && ctemp <= 'z' )
            inext = (ctemp - 'a') ;
          else inext = (ctemp-'1')+(size>>1) ;
          swap (&ctemp, &str[inext]);
        } while ( ctemp != str[inext] ) ;
    
        while ( (restartIndex < mid) && str[restartIndex] == ('a'+restartIndex) ) {
          restartIndex ++ ;
        }
    
    
        if ( restartIndex < mid ) {
          ctemp = str[restartIndex] ;
        } else break ;
      }
    }
     
  • Amit

    o(n) time and o(1) space
    //convert abcde12345 to a1b2c3d4e5
    #include
    #include
    #define swap(x,y,c) c=x,x=y,y=c
    void myfunc(char a[],int low,int high)
    {
    int j=high,k=(j+low)/2,i=low+1,l=0,c1=0;
    char c;
    if(high<=low)
    return;
    while(a[i]!='')
    {
    while(a[i]!='' && ilow+1)
    {
    swap(a[i],a[k],c);
    i++;
    }
    swap(a[i],a[k+l],c);
    i++;
    l++;
    if(a[i]==”)
    break;
    }
    if(a[i]==”)
    break;
    low=i;
    i++;
    k=(high+low)/2;
    l=0;
    }
    printf(“%d\t%d\t%s\t%d\n”,i,high,a,c1);
    }
    int main()
    {
    char a[]=”abcdefgh12345678″;
    myfunc(a,0,strlen(a));
    printf(“%s”,a);
    return 0;
    }

  • a2

    Could somebody plz explain me what is the role of ” shift ” variable in the code ? I am not understanding that.

    • Aashish

      For joining first two sub-strings, we must know the size of the first sub-string. “shift” variable is used to keep track of the size of the first sub-string. As we go on merging the sub-strings, the size of the first sub-string is increased by the size of the second sub-string. Follow the example which explains how the sub-strings are being merged.

  • sharat

    Hi Ashish,

    Can you please walk through the cycle leader iteration algo for this a 1 b 2 c 3 d 4 e 5. I am struggling to understand this algo..May be I am missing something.. Please suggest any tips, which might help me understand this algo better.

    Thanks,
    Sharat

    • Aashish

      I encourage you to do some paper work and analyze how positions are being calculated and How cycles are formed.

      This is the simplest form of input, already in the form 3^k + 1.
      We can directly apply cycle leader iteration algo.

      0 1 2 3 4 5 6 7 8 9
      a 1 b 2 c 3 d 4 e 5

      Applying cycle leader iteration, starting with 1:
      1->5->7->8->4->2->1

      0 1 2 3 4 5 6 7 8 9
      a b c 2 e 1 d 3 4 5

      Applying cycle leader iteration, starting with 3:
      3->6->3

      0 1 2 3 4 5 6 7 8 9
      a b c d e 1 2 3 4 5

      We are done.

      • Sharat

        Ah! Makes sense now.. Thanks a ton!

         
        /* Paste your code here (You may delete these lines if not writing code) */
         
  • Sandeep

    How about this?

     
    #include<stdio.h>
    #include<stdlib.h>
    
    
    void swap(char *a, char *b)
    {
            char temp;
            temp = *a;
            *a = *b;
            *b = temp;
    
    }
    
    int main()
    {
            char arr[] = "a1b2c3d4";
            int size = sizeof(arr)/sizeof(arr[0]);
            int start = 1; 
            int end = size -2;
    
            while(start < end)
            {
                    for(int i=start;i<end;i+=2)
                    {
                            swap(&arr[i],&arr[i+1]);
                    }
                    start++;
                    end--;
            }
            printf("%s\n",arr);
    
            return 0;
    }
    
     
    • a2

      This is correct , right ?
      What will be the time complexity for this ? O(n^2) ??

  • anon

    Can we generalize this algorithm to the convert strings like
    “a1b1c1…..anbncn” into the following form

    “a1a2…anb1b2…bnc1c2…cn”

  • supreeth

    for(i=1,j=0;i<strlen(s);i++)
    temp1[j++]=s[i];
    for(i=0,j=0;i<strlen(s);i++)
    temp2[j++]=s[i];
    s1=strcat(temp2,temp1);

  • supreeth
     
    /* Paste your code here (You may delete these lines if not writing code) */
    for(i=1;i<strlen(s);i+=2)
       temp1[j++]=s[i];
    for(i=1,j=0;i<strlen(s);i+=2)
       temp2[j++]=s[i];
    s=strcat(temp2,temp1);
    
    
    
    
     
    • Aashish

      This is not an in-place algorithm. The space complexity is O(N).
      in-place algorithm means a space complexity of O(1).

  • coder
     
    /* O(n^2) approach :
    #include<stdio.h>
    #include <ctype.h>
    int main()
    {
    char str[]={'a','1','b','2','c','3','d','4'};
    int i=0;
    int j=7;
     while ( i <= j ) 
     {
     while ( isalpha( str[i] ))  i++; 
    
     while( isdigit ( str[j] )) j--;
     char  temp = str[i];
     str[i] = str[j];
     str[j] = temp;
    
     }
    
    printf("%c",str[0]);
    printf("%c",str[1]);
    printf("%c",str[2]);
    printf("%c",str[3]);
    printf("%c",str[4]);
    printf("%c",str[5]);
    printf("%c",str[6]);
    printf("%c",str[7]);
    return 0;
    }
    
    O(n) approach :
    
    Firstly, I took the idea of quick Sort, to separate the letters and numbers.
    
    Then, which help me in their ascii values, I could know the correct position for each
    character and I try to put it in, the while loop ensures me that it works
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    
    using namespace std;
    
    int main(){
    	char str[1000];
    	
    	while(cin >> str){	
    		int len = strlen(str);
    		int i=0, j=len-1;
    	
    		while (i < len/2 && len/2 <= j) {
    			while ( isalpha (str[i]) ) i++;
    			while ( isdigit (str[j]) ) j--;
    			swap ( str[i], str[j] );
    			i++; j--;
    		}
    		if (isdigit(str[len/2-1])) swap(str[len/2], str[len/2-1]);
    	
    		int count = 0;
    		for ( int i = 0; i < len/2; ++i ) while ( str[i] - 'a' != i)
    			swap(str[i], str[(str[i] - 'a')]), count++;
    	
    		for ( int j = len - 1; j >= len/2; --j ) while ( (str[j] & 15) != j - len/2 + 1)
    			swap( str[j], str[ (str[j] & 15) + len/2 - 1 ] ), count++;
    	
    		cout << str << " " << count << endl;
    	} 
    */
     
    • coder
       
      O(n*n) :
      #include<stdio.h>
      #include <ctype.h>
      int main()
      {
      char str[]={'a','b','1','2','3','4','c','d'};
      int i=0;
      int n=7;
      while(!isdigit(str[i]))
      {i++;}
      int j=i;
      
      while(!isalpha(str[j]))
      {j++;}
      
      while(j<=n)
      { 
      char temp = str[i];
       str[i] = str[j];
       //shifarrayrightby1(a,i+1,j)
      {
        for(int k=j;k>i+1;k--)
        { 
          str[k] = str[k-1]; 
        }
      
      }
      str[i+1]=temp;
      i++;
      j++; 
      }
      printf("%c",str[0]);
      printf("%c",str[1]);
      printf("%c",str[2]);
      printf("%c",str[3]);
      printf("%c",str[4]);
      printf("%c",str[5]);
      printf("%c",str[6]);
      printf("%c",str[7]);
      return 0;
      }
      
       
    • Aashish

      Please read the question carefully. You are not maintaining the relative ordering of the alphabets and digits.

      e.g. If the input is a1b2c3d4, output should be abcd1234

      But, your program is outputting: adbc2314

      Check here: https://ideone.com/DhBgy

      • coder
         
        ignore the first O(n*n) approach , see 2nd approach
         
        • Aashish

          Your second program is not working in all cases.
          See here:

          Check for the below inputs:
          a1b2c3d4e5f6g7h8i9j1

          a1b2c3d4e5f6g7h8i9j1k2l3m4

          Please let me know the steps you are using.

          • coder
             
            Dude code is running fine
            I am also printing count 
            which is for analyses of
            time complexity 
            
             
          • nishit

            cant we use linkedlist instead of array,even positioned data will be removed and appended at the end
            for example:
            1a2b3c
            1 is deleted and appended at the end
            a2b3c1
            2 is deleted and appended at the end
            ab3c12
            3 is deleted and appended at the end
            abc123
            please correct me,if i am wrong..

          • Manoj

            public static void moveEvenElementToEnd(char arr[]){
            int len=(arr.length-1)/2+1;
            int index=0;
            char arr1[]=new char [arr.length];
            for(int i=0;i<arr.length ;i++){
            if(i%2==1){
            arr1[len]=arr[i];
            len++;
            }
            else{
            arr1[index]=arr[i];
            index++;
            }
            }
            }

  • anudeep

    Notes:
    1. If the array size is already in the form 3^k + 1, We can directly apply cycle leader iteration algorithm. There is no need of joining.

    Even if size is not in form of 3^k + 1, it appearscycle iteration algo is applicable.

    Old index New index
    0 0
    1 13
    2 1
    3 14
    4 2
    5 15
    6 3
    7 16
    8 4
    . .
    . .
    25 25

    Correct me if iam wrong

     
    /* Paste your code here (You may delete these lines if not writing code) */
     
    • Aashish

      In the first look, it seems that you can do it without splitting into size of form 3^k + 1. But, observe that while shifting the items to their correct position, cycles are formed.

      See the below link for cases where it doesn’t work.

      https://ideone.com/S302T

  • rahul

    @aashish

    What do you mean by only 3^k+1??
    We can always divide the string into parts of 3^k+1 and then apply the above suggested algo.

    • Kartik

      I think the given string will always be of even length. And any even length string can be divided in the parts of size 3^k + 1. The number ‘2’ itself is of the form 3^k + 1.

      • http://www.facebook.com/barnwal.aashish Aashish

        Please take a closer look at the algorithm. Before applying the cycle leader algorithm, it is compulsory to cut out the largest prefix sub-string of size of the form 3^k + 1. The cycle leader iteration algorithm is applied to the parts of the string which is of the form 3^k+1 only and not the whole string unless it is already in the form 3^k+1.
        The statement means that if the string size is of any other form, it is necessary to split it into sub-strings of size 3^k+1 before applying cycle leader iteration algorithm.

  • aj

    I think there is another approach. Not sure whether it will be O(n).I will show the steps involved.
    let the string be
    a1b2c3d4e5f6
    ab12c3d4e5f6 // 1 jumps over by 0 places.
    abc213d4e5f6 //notice here 1 jumps over by one number
    abc123d4e5f6 //we bring it back.
    abcd2314e5f6 // 1 jumps over by 2 places.
    abcd1234e5f6 //bring back
    abcde23415f6 // 1 jumps over by 3 places.
    abcde12345f6 //bring back 1
    abcdef234516 // 1 jumps over by 4 places
    abcdef123456 //bring it back.

    time for bringing 1 back is something I need to think about. Otherwise I suppose it would be O(n)

    • aj

      @kartik what do you think???

      • Aashish

        The steps are not clear:
        a1b2c3d4e5f6
        1. ab12c3d4e5f6 // 1 jumps over by 0 places.
        2. abc213d4e5f6 //notice here 1 jumps over by one number
        3. abc123d4e5f6 //we bring it back.

        In step#1, 1 jumps by 1 place. What is meant by 0 place.

        In step#2, If 1 jumps by 1 place, the result should be
        ab21c3d4e5f6, how c is shifted from its position.

        • aj

          At each step we swap 1 with alphabets and then bring 1 back to its position. see this example.
          a1b2c3d4e5f6
          1. ab12c3d4e5f6 // swap b & 1, jump = 0;
          2. abc213d4e5f6 // swap c & 1, jump = 1;
          3. abc123d4e5f6 //we bring it back. 2,1—>1,2
          4. abcd2314e5f6 // swap d & 1; jump = 2;
          5. abcd1234e5f6 // bring it back. 2,3,1—>1,2,3
          6. abcde23415f6 // swap e & 1; jump = 3;
          7. abcde12345f6 // bring it back.
          8. abcdef234516 // swap f & 1; jump = 4
          9. abcdef123456 // bring it back

  • soumya

    is there any significance of dividing the sub-array only into 3^k+1 ?? (why not into 4^k?)

  • Bogdan

    Why is the cycle leader algo only applicable to 3^k + 1 sized strings?