1

Java Experts need your help.

Today I was asked this questions in one of the interviews which I could not solve it. So I need a solution as to how should I solve this ;

Reversing a String

Input  : Hello, World!
Output : olleH, dlroW!

In this case alphanumerics reverses and rest remains in the same place that means comma and Exclamation remains in their same place.

You can make use of only 4 String functions to get the answer;

  1. charAt(c)
  2. length()
  3. setCharAt(i,c)
  4. boolean isAlphaNumeric()

I tried the following code ;

public void String(String str){     
    String temp;

    for(int i=str.length-1;i>=0;i--){
        temp = temp + str.charAt(i);
    }
}

But the above code reverses the whole string.

user2864740
  • 60,010
  • 15
  • 145
  • 220
skyrocker
  • 199
  • 2
  • 8
  • 20
  • 2
    Careful of the words you use: "inplace" generally means in the same memory location without creating another copy. And, since Java strings are immutable, that's impossible. – paxdiablo Nov 02 '13 at 00:30

4 Answers4

2
public String reverseString(String str){     
        String temp = "", result = "";
        for(int i=0;i<str.length();i++)
            if ( (str.charAt(i)>='A' && str.charAt(i)<='Z')
                || (str.charAt(i)>='a' && str.charAt(i)<='z')
                || (str.charAt(i)>='0' && str.charAt(i)<='9') )
                temp = str.charAt(i) + temp;
            else {
                result += temp + str.charAt(i);
                temp = "";
            }

        result += temp;
        System.out.println(result);
        return result;
    }
hasan
  • 23,815
  • 10
  • 63
  • 101
2

You can try to find all words with regex and then use Matchers method appendReplacement and appendTail to replace founded words with reversed version. To produce reversed version of word you can use

StringBuilder().append(word).reverse().toString();

Here is how you can do it

public static void main(String[] args) throws Exception {
    Pattern p = Pattern.compile("\\p{IsAlphabetic}+");

    StringBuffer sb = new StringBuffer();

    Matcher m = p.matcher("Hello, World!");
    while (m.find()) {
        m.appendReplacement(sb, reverseWord(m.group()));
    }
    m.appendTail(sb);

    System.out.println(sb);
}

private static String reverseWord(String word) {
    return new StringBuilder().append(word).reverse().toString();
}

output:

olleH, dlroW!
user2864740
  • 60,010
  • 15
  • 145
  • 220
Pshemo
  • 122,468
  • 25
  • 185
  • 269
  • +1 Very nice. I never how understood appendReplacement/appendTail before! It also seems like this should show up someone in an answer to my recent question (http://stackoverflow.com/questions/19737653/one-off-equivalent-for-regex-replace-with-function-evaluation) – user2864740 Nov 02 '13 at 00:49
  • While I'd use this answer in real life, the OP has some silly interview requirements: "You can make use of only 4 String functions to get the answer ; 1) charAt(c) 2) length() 3) setCharAt(i,c) 4) boolean isAlphaNumeric()" – user2864740 Nov 02 '13 at 00:52
  • 1
    @hasan That is why I upvoted your answer. Anyway in real life you could upgrade it even more using enhanced for loop like `for (char ch: str.toCharArray()){...}`, appending to StringBuilder instead of `someString += anotherString` in loop and using `Character.isDigit(ch)||Character.isAlphabetic(ch)` in `if`. Anyway your answer should be accepted one. – Pshemo Nov 02 '13 at 01:00
  • isAlphaNumeric() is a method in StringUtils class which is not a java native class. I can use Character.isLetterOrDigit – hasan Nov 02 '13 at 01:04
0

Start by splitting the string into words using str.split('[^a-zA-Z]').

Then loop through the array and reverse each part as you did above. Finally, join the string together again. To get an array of separators in order, just use str.split('[a-zA-Z]')

Example:

String[] words=str.split('[^a-zA-Z]');
String[] separators=str.split('[a-zA-Z]');

//Left as an exercise: reverse each element of the words array (as you did in the original question)

int offset=0;
//Left as an exercise: If the sentence starts with punctuation, increment offset by one and insert the punctuation at the beginning

StringBuilder sb = new StringBuilder();
for(int i=0;i<words.length;i++)
{
    sb.append(words[i]);
    if(i+offset<separators.length)
    {
        sb.append(separators[i+offset]);
    }
}

EDIT:

I just read the changes to the question specifying which methods can be used. It is fairly simple to replace split with a manual implementation for this specific case, and I leave it as an exercise. This answer is meant to be a pseudocode idea for how to implement this task, not a copy-paste solution.

Flight Odyssey
  • 2,267
  • 18
  • 25
0

setCharAt isn't string functions as String is immutable, however you can do this with either a char array or a StringBuilder (which just wraps a char array). isAlphaNumeric isn't a standard method anywhere that I can find however Character.isAlphabetic is what I believe you want. This is using as close as I could get to following your restrictions:

private static CharSequence reverseWords( CharSequence in )
{
    StringBuilder sb = new StringBuilder( in );
    for( int i = 0, len = sb.length(); i < len; i++ )
    {
        if( Character.isAlphabetic( sb.charAt( i ) ) )
        {
            int end = i;
            while( ++end < len && Character.isAlphabetic( sb.charAt( end ) ) );
            int j = end - 1;
            while( j > i )
            {
                char temp = sb.charAt( i );
                sb.setCharAt( i++, sb.charAt( j ) );
                sb.setCharAt( j--, temp );
            }
            i = end;
        }
    }
    return sb;
}

However if you wanted to use a char array directly without a StringBuilder:

private static String reverseWords( String in )
{
    char[] chars = in.toCharArray();
    for( int i = 0, len = chars.length; i < len; i++ )
    {
        if( Character.isAlphabetic( chars[i] ) )
        {
            int end = i;
            while( ++end < len && Character.isAlphabetic( chars[end] ) );
            int j = end - 1;
            while( j > i )
            {
                char temp = chars[i];
                chars[i++] = chars[j];
                chars[j--] = temp;
            }
            i = end;
        }
    }
    return String.valueOf( chars );
}
LINEMAN78
  • 2,562
  • 16
  • 19