Category: Easy | Concepts used: String buffer accumulation, character filters, regex compile overhead
Problem Statement
Given a string, remove all spaces from it.
Input : "Hello World" Output: "HelloWorld"
Input : " a b c " Output: "abc"
Examples (with edge scenarios)
| # | Input | Output | Why |
|---|---|---|---|
| 1 | "Hello World" | "HelloWorld" | The single space is removed |
| 2 | "" | "" | Empty string yields empty output |
| 3 | " " | "" | All space characters are removed |
| 4 | "NoSpacesHere" | "NoSpacesHere" | Unchanged output |
| 5 | "a\tb\nc" | Clarify | Literal space character only, or all whitespace (tabs/newlines)? Always clarify this constraint. |
โ ๏ธ Common Beginner Mistake
Mistake Impact Fix Concatenating characters using +=inside a loopCreates new Stringobjects continuously in the heap, causing memory bottlenecksUse StringBuilderfor O(1) character appendingUsing replaceAllwithout understanding its overheadCompiles regular expression patterns internally, slowing down execution Use replace(" ", "")for literal swaps as it is faster
Before You Code: Clarify the Contract
Before choosing an algorithm, confirm how null and empty strings should behave, whether comparison is case-sensitive, and whether spaces or punctuation count. Java char values are UTF-16 code units, not always complete human-visible Unicode characters, so international text may require code points or grapheme-aware libraries.
Analogy: Sifting Sand at a Beach
Imagine you are sifting a bucket of beach sand (the string) to remove stones (spaces):
- You have a sieve (the conditional loop check) and a clean bucket (the StringBuilder buffer).
- You pour the sand through. The fine grains of sand (non-space characters) pass straight through the sieve into the clean bucket (
result.append(ch)). - The stones (spaces) are caught by the sieve and thrown away (skipped).
- Your clean bucket ends up with pure, stone-free sand!
Solution 1 โ Loop + StringBuilder (Optimal Manual)
This is the standard manual approach using a mutable string buffer.
Intuition
By checking each character individually, we only append non-space characters to our StringBuilder buffer. This prevents intermediate string allocations in the heap.
public class RemoveSpaces {
public static String removeSpaces(String str) {
if (str == null) {
return null;
}
StringBuilder result = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (ch != ' ') { // Skip plain space
result.append(ch);
}
}
return result.toString();
}
public static void main(String[] args) {
System.out.println(removeSpaces("Hello World")); // "HelloWorld"
System.out.println(removeSpaces(" a b c ")); // "abc"
System.out.println(removeSpaces("")); // ""
}
}
Output:
HelloWorld
abc
Solution 2 โ Using String.replace() (Concise & Optimized Literal)
This is the preferred one-liner for literal space replacement.
Intuition
Javaโs String.replace() replaces all occurrences of a target literal character sequence. Because it does not compile a regular expression pattern, it is highly optimized.
public class RemoveSpacesReplace {
public static String removeSpaces(String str) {
if (str == null) {
return null;
}
return str.replace(" ", ""); // Replaces every literal space with an empty string
}
public static void main(String[] args) {
System.out.println(removeSpaces("Hello World")); // "HelloWorld"
System.out.println(removeSpaces(" a b c ")); // "abc"
}
}
Solution 3 โ Using Regex (replaceAll)
This approach uses a regular expression to match and strip all forms of whitespace.
Intuition
If the requirement dictates removing all whitespace (including tabs \t, carriage returns \r, and newlines \n), we use the regex pattern \\s.
public class RemoveSpacesRegex {
public static String removeSpaces(String str) {
if (str == null) {
return null;
}
return str.replaceAll("\\s+", ""); // Removes all whitespace characters
}
public static void main(String[] args) {
System.out.println(removeSpaces("a\tb\nc")); // "abc"
}
}
Output:
abc
๐ Visual Flowchart
graph TD
Start["Input String S"] --> NullCheck{"S is null?"}
NullCheck -->|Yes| RetNull["Return Null"]
NullCheck -->|No| InitBuilder["Initialize StringBuilder sb"]
InitBuilder --> Loop{"i < S.length()?"}
Loop -->|Yes| Fetch["ch = S.charAt(i)"]
Fetch --> CheckSpace{"ch == ' '?"}
CheckSpace -->|Yes| Skip["i++"]
CheckSpace -->|No| Append["sb.append(ch)"]
Append --> Skip
Skip --> Loop
Loop -->|No| Convert["sb.toString()"]
Convert --> End["Return result"]
Interviewer Insights
This question tests string builder allocation rules and regular expression overhead trade-offs.
Follow-up questions you might get:
- โWhat is the performance difference between replace() and replaceAll() in Java?โ โ
replace(" ", "")looks for literal targets. Under the hood, it performs rapid character scans.replaceAll("\\s", "")parses the input pattern as a regular expression, compiles it, and uses a pattern matcher. This is much slower and consumes more memory.- Tip: Always use
replace()for literal string swaps and reservereplaceAll()for pattern/regex swaps.
- โWhy is StringBuilder better than String concatenation in loops?โ โ Each concatenation (
str = str + ch) copies the old string characters to build the new one, resulting in a quadratic (O(N^2)) time penalty.StringBuilderuses a resizable internal character array, yielding linear (O(N)) runtime.
Quick Recap
| Approach | Time Complexity | Auxiliary Space Complexity | Handles Tabs / Newlines? | Interview Signal |
|---|---|---|---|---|
StringBuilder Loop | (O(N)) | (O(N)) (for builder) | Customizable | Demonstrates core logic control and memory efficiency |
replace(" ", "") | (O(N)) | (O(N)) | No | Practical, highly optimized literal one-liner |
replaceAll("\\s", "") | (O(N)) (w/ overhead) | (O(N)) | Yes | Comprehensive pattern matching, but compiles regex |
- Author
- TechByteByByte Editorial Team
- Reviewed by
- TechByteByByte Admin
- Published
- Last reviewed