开发者

Transposing and Untransposing a String in java

I have been working on two methods that will Transpose and Untranspose a String respectively. The solutions that I have come up with both work to the best of my knowledge. I just want to know if I could have solved these problems in a simpler way. My code seems like it is too long for the task that is being performed. The first method, transpose(), will take a String as a parameter and transpose it. If "bridge" is entered, the output will be "bergid". Likewise, with the unTranspose() method, if the user enters "bergid", the output will be "bridge".

  public void transpose( String s )
  {
      String t = ""; 
      int end = s.length() - 1;


        for ( int i = 0; i < s.length()  / 2; i++ )
        {
            t += Character.toString( s.charAt( i ) ) + Character.toString( s.charAt( end ) );
            end--;
        }
        // Lenth of String is odd
        if ( s.length() % 2 == 1 )
        {
            // add character in middle of String to the end of开发者_JS百科 the new String
            t+= Character.toString( s.charAt( s.length() / 2 ) );
        }

        System.out.println( t );
  }

    public void unTranspose( String s )
    {
    String t = ""; 

      // Length of String is odd
      if ( s.length() % 2 == 1 )
      {
      for ( int i = 0; i < s.length(); i+=2 )
      {
        t+= Character.toString( s.charAt( i ) );
      }

      for ( int i = s.length() - 2; i > 0; i -= 2 )
      {
        t += Character.toString( s.charAt( i ) );
      }

         System.out.println( t );
      }



   // Length of String is even
   else if ( s.length() % 2 == 0 )
   {
    for ( int i = 0; i < s.length() - 1; i+=2 )
    {
       t+= Character.toString( s.charAt( i ) );
    }

    for ( int i = s.length() - 1; i > 0; i -= 2 )
    {
        t+= Character.toString( s.charAt( i ) );
    }


    System.out.println( t );
}
   }

My code looks horrible. I'm still not used to formatting my code correctly. Please bear with me.

Thanks for your time


Definition

         transpose
         --------->
"123Xcba"            "1a2b3cX"
        <-----------
        untranspose


Using Recursion

public static String transpose(String str) {

    if (str == null || str.length() == 1 || str.length() == 2) {
        return str;
    } else {
        return str.substring(0, 1) + str.substring(str.length() -1, str.length()) + transpose(str.substring(1, str.length() -1) );
    }
}

public static String untranspose(String str) {
    if (str == null || str.length() == 1 ||str.length() == 2) {
        return str;
    } else {
        return  str.substring(0, 1) + untranspose(str.substring(2, str.length())) + str.substring(1, 2);
    }
}


This solution has a nice symmetry.

public static String transpose(String s) {
    StringBuilder sb = new StringBuilder();
    sb.setLength(s.length());
    for (int i = 0, j = s.length() - 1, x = 0; i <= j; ) {
        sb.setCharAt(x++, s.charAt(i++));
        if (i > j) break;
        sb.setCharAt(x++, s.charAt(j--));
    }
    return sb.toString();
}

public static String untranspose(String s) {
    StringBuilder sb = new StringBuilder();
    sb.setLength(s.length());
    for (int i = 0, j = s.length() - 1, x = 0; i <= j; ) {
        sb.setCharAt(i++, s.charAt(x++));
        if (i > j) break;
        sb.setCharAt(j--, s.charAt(x++));
    }
    return sb.toString();
}

This makes it obvious that the logic between the two methods are identical; the only difference is that:

  • In transpose, i and j are read indices, x is a write index
  • In untranspose, i and j are write indices, x is a read index (i.e. it's the other way around)

It's really quite simple:

  • i always goes from beginning to middle of string
  • j always goes from end to middle of string
  • x always goes from beginning to end of string
  • If the input is of odd length, inevitably i == j eventually
    • At that point you only need i, so break

Lalith came up with the first recursive solution; this one is essentially the same, with minor modification:

public static String transpose(String s) {
  int L = s.length();
  return (L < 2) ? s
    : s.substring(0, 1) + s.substring(L-1, L) + transpose(s.substring(1, L-1));
}

public static String untranspose(String s) {
  int L = s.length();
  return (L < 2) ? s
    : s.substring(0, 1) + untranspose(s.substring(2, L)) + s.substring(1, 2);
}


Here is my response to this - The main issue I saw with your code is you creating Strings as temporary objects in multiple areas of the code - This makes it very inefficient as well as very slow. The other issue is that you want to externalize all you can from the loops. I have compiled it and run it and it works.

package com.rch.test;

public class Transposer
{
    public static String transpose(String s)
    {
        int length = s.length();
        int end = length - 1;

        StringBuilder t = new StringBuilder();
        for (int i = 0; i < length / 2; i++)
        {
            t.append(s.charAt(i));
            t.append(s.charAt(end));
            end--;
        }

        // Length of String is odd
        if (length % 2 == 1)
        {
            // add character in middle of String to the end of the new String
            t.append(s.charAt(length / 2));
        }
        return t.toString();
    }

    public static String unTranspose(String s)
    {
        int length = s.length();
        StringBuilder t = new StringBuilder();

        if (length % 2 == 1)
        {
            for (int i = 0; i < length; i += 2)
            {
                t.append(s.charAt(i));
            }

            for (int i = length - 2; i > 0; i -= 2)
            {
                t.append(s.charAt(i));
            }
        }
        else if (length % 2 == 0)
        {
            for (int i = 0; i < length - 1; i += 2)
            {
                t.append(s.charAt(i));
            }

            for (int i = length - 1; i > 0; i -= 2)
            {
                t.append(s.charAt(i));
            }
        }
        return t.toString();
    }

    public static void main(String[] args)
    {
        String testString = "bridge";
        String transposedString = Transposer.transpose(testString); 
        String finalString = Transposer.unTranspose(transposedString);

        System.out.println("1)" + testString);
        System.out.println("2)" + transposedString);
        System.out.println("3)" + finalString);
    }
}

Output : 1)bridge 2)bergid 3)bridge


had a quick shot at doing your transpose method using a StringBuilder which usually makes these kind of operations simpler. This seems to work with your bridge example and also Strings of odd length.

public static void transpose( String s ) 
{
    StringBuilder sb = new StringBuilder(s);

    for( int i=1; i<sb.length(); i=i+2 ) {          
        sb.insert( i, sb.charAt( sb.length()-1 ) );         
        sb.deleteCharAt( sb.length()-1 );
    }

    System.out.println( sb.toString() );
}

Should give you enough ideas to implement the untranspose method yourself :+)


Here is a method that does not require different behavior based upon whether the length of the string is even or odd.

public static String transpose(String in)
{
    StringBuilder out = new StringBuilder();
    for (int i=0; i<in.length(); ++i)
    {
        out.append(in.charAt(i));
        out.append(in.charAt(in.length() - i - 1));
    }
    return out.substring(0, in.length());
}

public static String untranspose(String in)
{
    StringBuilder out = new StringBuilder();
    for (int i=0; i<in.length(); i+=2)
    {
        out.append(in.charAt(i));
    }
    StringBuilder reversedSecondHalf = new StringBuilder();
    for (int i=1; i<in.length(); i+=2)
    {
        reversedSecondHalf.append(in.charAt(i));
    }
    out.append(reversedSecondHalf.reverse());
    return out.toString();
}


Well, I was able to simplify the transpose method a bit:

public static String transpose(String s)
{
   StringBuilder sb = new StringBuilder();
   int i = 0;
   int length = s.length() - 1;
   while(i < length - i)
   {
      sb.append(s.charAt(i)).append(s.charAt(length - i));
      i++;
   }
   if(i == length - i) sb.append(s.charAt(i));
   return sb.toString();
}

Update

Tried my luck with untranspose -

public static String untranspose(String s)
{
   StringBuilder sb1 = new StringBuilder();
   StringBuilder sb2 = new StringBuilder();
   int length = s.length();
   int iopp = (length % 2 == 0) ? length - 1 : length - 2;
   for(int i = 0; i < length; i += 2, iopp -= 2)
   {
      sb1.append(s.charAt(i));
      if(iopp >= 0) sb2.append(s.charAt(iopp));
   }
   return sb1.append(sb2).toString();
}


Here is another solution that shows the symmetry between transposing and untransposing.

public static String transpose(String in)
{
    int length = in.length();
    StringBuilder out = new StringBuilder(in);
    for (int pos=1; pos<length; pos+=2)
    {
        swapCharacters(out, length-1, pos);
    }
    return out.toString();
}

public static String untranspose(String in)
{
    int length = in.length();
    StringBuilder out = new StringBuilder(in);
    for (int pos=length-1-(length%2); pos>0; pos-=2)
    {
        swapCharacters(out, pos, length-1);
    }
    return out.toString();
}

private static void swapCharacters(StringBuilder string, int oldPos, int newPos)
{
    char c = string.charAt(oldPos);
    string.deleteCharAt(oldPos);
    string.insert(newPos, c);
}


The expression can be quite short without becoming too difficult to understand.

/** Convert ABCDefg to AgBfCeD */
public static String transpose(String s){
    char[] ts = new char[s.length()];
    int i = 0, j = ts.length;
    for( int k = 0 ; k < ts.length ; k++ ){
        ts[k] = s.charAt(k%2==0 ? i++ : --j);
    }
    return new String(ts);
}
/** Convert AgBfCeD to ABCDefg */
public static String untranspose(String ts){
    char[] s = new char[ts.length()];
    int i = 0, j = ts.length();
    for( int k = 0 ; k < ts.length() ; k++ ){
        s[k%2==0 ? i++ : --j] = ts.charAt(k);
    }
    return new String(s);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜