1
\$\begingroup\$

Implement a method to perform basic string compression using the counts of repeated characters.

For example, the string "aabcccccaaa" would become "a2b1c5a3". If the "compressed" string would not become smaller than the original string, your method should return the original string. You can assume the string has only uppercase and lowercase letters (a - z).

My solution is:

GitHub

public class StringCompression {

  public static String compress(String input) {
    if (input == null) {
      return null;
    }

    StringBuilder output = new StringBuilder();

    char prevChar = input.charAt(0);
    int lengthSoFar = 1;

    for (int index = 1; index < input.length(); index++) {
      char currentChar = input.charAt(index);

      if (prevChar == currentChar) {
        lengthSoFar++;
      } else {
        output.append(prevChar);
        output.append(lengthSoFar);

        // reset counters
        prevChar = currentChar;
        lengthSoFar = 1;
      }
    }
    output.append(prevChar);
    output.append(lengthSoFar);

    return output.toString().length() <= input.length() ? output.toString() : input;
  }
}
\$\endgroup\$
1
  • \$\begingroup\$ i would suggest only one change, the character abbccc translates into a1b2c3 ...rather than doing this, just keep single characters directly. E.g: above string should translate to ab2c3 . Also, you are calling output.toString() twice, you can get by doing it only once. \$\endgroup\$ Nov 21, 2018 at 15:57

2 Answers 2

3
\$\begingroup\$

For input "fooo", the implementation returns "f1o3", which is the same length, and violates one of the requirements:

If the "compressed" string would not become smaller than the original string, your method should return the original string.

The fix is in the return statement: change <= to <.


Another corner case is when the input is empty, the statement char prevChar = input.charAt(0); will throw StringIndexOutOfBoundsException.


Lastly, a performance pitfall in the return statement, output.toString() creates a new string, therefore the following may result in double computation:

return output.toString().length() < input.length() ? output.toString() : input;

You could instead benefit from the length() method of StringBuilder:

return output.length() < input.length() ? output.toString() : input;
\$\endgroup\$
1
\$\begingroup\$

Generates an out of bounds exception if passed an empty (but not null) string.

The new StringBuilder() should be passed an initial size for the character buffer, to avoid continuous reallocations. Lacking any other reasonable value, I’d recommend passing in the original string length.

StringBuilder output = new StringBuilder(input.length());
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.