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;
 }
}
asked Nov 20, 2018 at 20:03
\$\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\$ Commented 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;
answered Nov 20, 2018 at 21:34
\$\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());
answered Nov 20, 2018 at 21:38
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.