views:

700

answers:

7

I am wondering which way to reverse a string in Java that is most efficient. Should I use some sort of xor method? The easy way would be to put all the chars in a stack and put them back into a string again but I doubt that's a very efficient way to do it. And please do not tell me to use some built in function in Java. I am interested in learning how to do it not to use an efficient function but not knowing why it's efficient or how it's built up.

+3  A: 

You said you don't want to do it the easy way, but for those Googling you should use StringBuilder.reverse:

String reversed = new StringBuilder(s).reverse().toString();

If you need to implement it yourself, then iterate over the characters in reverse order and append them to a StringBuilder. You have to be careful if there are (or can be) surrogate pairs, as these should not be reversed. The method shown above does this for you automatically, which is why you should use it if possible.

Mark Byers
Prefer `StringBuilder` to `StringBuffer` if you do not need thread safety.
Tom
-1 for not respecting "And please do not tell me to use some built in function in Java.". Sorry for that ;)I think Hultner would like to know the backgrounds / mechanics. However, the question should not be tagged java, I guess.
Tedil
@Tedil: Question should most likely be tagged homework.
Mark Byers
@Mark Byers I think Hultner should decide that. I think he really is interested, no matter if it's homework or not, how to do it. If it was homework, atleast he is interested, so does it matter to tag it or not?
Pindatjuh
@Tom: That's a good point, most likely thread-safety is not required here. I've updated my comment.
Mark Byers
+1 for pointing out you have to deal with surrogate pairs
Simon Nickerson
For those Googling they should consider answers here in context of the question.
John K
In a way homework, our homework is to reverse a string using a stack however I feel like that is not the right or best way to do it therefore I want to learn the best way to actually do it. And that's the reason I'm posting here, I want to learn. The Java assignments we do in school sometimes use extremely stupid ways to do stuff because everyone should understand it.
Hultner
+1 Google friendly.
Xorlev
@Hultner: You're right, that would be a poor way to do it. Using a stack would require boxing and unboxing of the characters.
Mark Byers
Wow, I'd have never thought of the surrogates! However, I've also never needed to reverse a string in my professional life.
jkff
+1  A: 

The following does not deal with UTF-16 surrogate pairs.

public static String reverse(String orig)
{
    char[] s = orig.toCharArray();
    int n = s.length;
    int halfLength = n / 2;
    for (int i=0; i<halfLength; i++)
    {
        char temp = s[i];
        s[i] = s[n-1-i];
        s[n-1-i] = temp;
    }
    return new String(s);
}
Simon Nickerson
+14  A: 

You say you want to know the most efficient way and you don't want to know some standard built-in way of doing this. Then I say to you: RTSL (read the source, luke):

This is the sourced code for AbstractStringBuilder#reverse which gets called by StringBuilder#reverse. I bet it does some stuff that you would not have considered for a robust reverse operation.

Tom
By the way... when I say "bet it does some stuff that you would have considered"... I was talking about surrogate pairs :-). You can see it in the code.
Tom
+1 for link to source. One of the best ways to learn how to implement something is to see how it is done in the real world.
Mark Byers
+1 for directly answering the question, being one of the few that's not on a tangent
John K
A: 

The fastest way would be to use the reverse() method on the StringBuilder or StringBuffer classes :)

If you want to implement it yourself, you can get the character array, allocate a second character array and move the chars, in pseudo code this would be like:

String reverse(String str) {
    char[] c = str.getCharArray
    char[] r = new char[c.length];
    int    end = c.length - 1

    for (int n = 0; n <= end; n++) {
        r[n] = c[end - n];
    }

    return new String(r);
}

You could also run half the array length and swap the chars, the checks involved slow things down probably.

rsp
The `String` class does not have a `reverse()` method.Also, your pseudo-code is wrong, as your arrays are sometimes 0-based and sometimes 1-based.
Simon Nickerson
rsp
No, still wrong. Now it will produce a string of length len-1. You want: `for (int n=0; n<len; n++) { r[n] = c[len-n-1]; }`
Simon Nickerson
This is correct imho, example: for a string of length 3 n=0,1,2 and copies chars at 3-0-1,3-1-1,3-2-1 which are 2,1,0
rsp
A: 

If you do not want to use any built in function, you need to go back with the string to its component parts: an array of chars.

Now the question becomes what is the most efficient way to reverse an array? The answer to this question in practice also depends upon memory usage (for very large strings), but in theory efficiency in these cases is measured in array accesses.

The easiest way is to create a new array and fill it with the values you encounter while reverse iterating over the original array, and returning the new array. (Although with a temporary variable you could also do this without an additional array, as in Simon Nickersons answer).

In this way you access each element exactly once for an array with n elements. Thus giving an efficiency of O(n).

NomeN
A: 

I'm not really sure by what you mean when you say you need an efficient algorithm.

The ways of reversing a string that I can think of are (they are all already mentioned in other answers):

  1. Use a stack (your idea).

  2. Create a new reversed String by adding characters one by one in reverse order from the original String to a blank String/StringBuilder/char[].

  3. Exchange all characters in the first half of the String with its corresponding position in the last half (i.e. the ith character gets swapped with the (length-i-1)th character).

The thing is that all of them have the same runtime complexity: O(N). Thus it cannot really be argued that any one is any significantly better than the others for very large values of N (i.e. very large strings).

The third method does have one thing going for it, the other two require O(N) extra space (for the stack or the new String), while it can perform swaps in place. But Strings are immutable in Java so you need to perform swaps on a newly created StringBuilder/char[] anyway and thus end up needing O(N) extra space.

MAK
A: 

public class ReverseInPlace {

static char[] str=null;

public static void main(String s[]) {
  if(s.length==0)
    System.exit(-1);

   str=s[0].toCharArray();

   int begin=0;
   int end=str.length-1;

   System.out.print("Original string=");
   for(int i=0; i<str.length; i++){
     System.out.print(str[i]);
   }

   while(begin<end){
      str[begin]= (char) (str[begin]^str[end]);
      str[end]= (char)   (str[begin]^str[end]);
      str[begin]= (char) (str[end]^str[begin]);

      begin++;
      end--;       
   }

   System.out.print("\n" + "Reversed string=");
   for(int i=0; i<str.length; i++){
     System.out.print(str[i]);
   }

}

}

abiolaaye
While I thank you for your answer it's been half a year since I wrote this questiont and the problem have since long been resolved but thanks for your answer.
Hultner