Placement Prep

Program to Remove Spaces from a String: Python & C

Remove all whitespace from a string in Python and C: two-pointer, build-new-string, and library one-liners, with complexity analysis and edge cases.

By FACE Prep Team 5 min read
strings python c-programming dsa placement-prep two-pointer whitespace

Removing every space from a string is a single-pass O(n) problem. The approach you choose, whether in-place rewrite, new-string build, or library one-liner, signals how you think about memory trade-offs.

The Problem and What “Remove Spaces” Actually Means

The task: given a string that may contain whitespace characters at any position, return a version with all spaces removed, not just the leading and trailing ones.

  • Input: "Hello World 2026" → Output: "HelloWorld2026"
  • Input: "F a c e" → Output: "Face"
  • Input: "" → Output: "" (empty string, handled without special-casing)
  • Input: " " → Output: "" (all-space string produces empty output)
  • Input: "abc" → Output: "abc" (no spaces, input returned unchanged)

One definition question matters before writing code: does “space” mean only the ASCII space character (code point 32), or all whitespace (tabs, newlines, carriage returns)? The approach sections below flag when the answer changes the implementation. For most placement problems, only ASCII space is tested, but real-world text processing almost always needs the broader definition.

Approach 1 — Two-Pointer In-Place Rewrite

Two pointers: r (read index) walks every character of the array; w (write index) advances only when the character at r is not a space. Non-space characters get written to position w, then w increments. After the loop, position w becomes the new string terminator.

The key invariant is that w never exceeds r. At every step, the character being read (str[r]) has already been written to its new position (or is about to be) before w could catch up. This means the algorithm is safe on a single buffer with no risk of overwriting a character before it has been read.

Time complexity: O(n), since every character is examined exactly once. For a detailed breakdown of how auxiliary and total space complexity are computed, see the linked guide; here the auxiliary space is O(1), just two integer indices regardless of input size.

Python (simulated in-place using a list)

Python strings are immutable, so “in-place” means converting to a list first, applying the two-pointer logic, and joining the result:

def remove_spaces_two_pointer(s: str) -> str:
    chars = list(s)   # mutable copy
    w = 0
    for r in range(len(chars)):
        if chars[r] != ' ':
            chars[w] = chars[r]
            w += 1
    return ''.join(chars[:w])

# Verification
print(remove_spaces_two_pointer("Hello World 2026"))  # HelloWorld2026
print(remove_spaces_two_pointer(""))                  # (empty string)
print(remove_spaces_two_pointer("   "))               # (empty string)
print(remove_spaces_two_pointer("abc"))               # abc

C (true in-place on a char array)

In C, the char array is mutable, so the rewrite happens directly in the original buffer:

#include <stdio.h>

void remove_spaces(char *str) {
    int r = 0, w = 0;
    while (str[r] != '\0') {
        if (str[r] != ' ') {
            str[w] = str[r];
            w++;
        }
        r++;
    }
    str[w] = '\0';
}

int main(void) {
    char s1[] = "Hello World 2026";
    remove_spaces(s1);
    printf("%s\n", s1);   /* HelloWorld2026 */

    char s2[] = "   ";
    remove_spaces(s2);
    printf("[%s]\n", s2); /* [] */

    char s3[] = "abc";
    remove_spaces(s3);
    printf("%s\n", s3);   /* abc */

    return 0;
}

The write index w never overtakes the read index r, so there is no aliasing problem. The source character at str[r] is always read before it could be overwritten by a future write to str[w].

Approach 2 — Build a New String

Allocate (or build) a result container and append only non-space characters. The code is slightly simpler to read than the two-pointer version, at the cost of O(n) auxiliary space for the output.

Python

def remove_spaces_new_string(s: str) -> str:
    result = []
    for ch in s:
        if ch != ' ':
            result.append(ch)
    return ''.join(result)

# Verification
print(remove_spaces_new_string("Hello World 2026"))  # HelloWorld2026

A list accumulator is used rather than repeated string concatenation (result += ch) because each concatenation in Python creates a new string object, making the naive version O(n²) in total. The list-then-join pattern is O(n) and is the idiomatic approach in Python for building strings character by character.

C (using a second buffer)

#include <stdio.h>
#include <string.h>

void remove_spaces_new(const char *src, char *dst) {
    int w = 0;
    for (int r = 0; src[r] != '\0'; r++) {
        if (src[r] != ' ') {
            dst[w] = src[r];
            w++;
        }
    }
    dst[w] = '\0';
}

int main(void) {
    const char src[] = "Hello World 2026";
    char dst[sizeof(src)];
    remove_spaces_new(src, dst);
    printf("%s\n", dst);  /* HelloWorld2026 */
    return 0;
}

This version leaves the original string untouched, which matters when the caller needs to keep the original for logging, error messages, or further processing.

Approach 3 — Library One-Liners

For most production Python code, a built-in one-liner is the right choice. The two most common options differ in how they define “whitespace”:

s = "Hello World 2026"

# Removes only ASCII space (code point 32)
print(s.replace(' ', ''))           # HelloWorld2026

# Removes ALL whitespace — spaces, tabs, newlines, carriage returns
print(''.join(s.split()))           # HelloWorld2026

Both return "HelloWorld2026" for the test string. The difference appears with "\tHello\n World":

  • .replace(' ', '') produces "\tHello\nWorld" (tabs and newlines survive)
  • ''.join(s.split()) produces "HelloWorld" (all whitespace gone)

Python’s str.split() documentation specifies that calling split() with no argument splits on any whitespace run and discards empty strings between separators. That makes it the idiomatic “strip everything” pattern.

C++ — erase-remove idiom

#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>

int main() {
    std::string s = "Hello World 2026";
    s.erase(std::remove_if(s.begin(), s.end(),
                           [](unsigned char c){ return c == ' '; }),
            s.end());
    std::cout << s << "\n";  // HelloWorld2026
    return 0;
}

The std::remove_if reference explains that remove_if moves non-matching elements to the front and returns an iterator to the new logical end. The .erase() call trims the string to that length. To remove all whitespace instead of only spaces, replace c == ' ' with ::isspace(c).

Complexity summary

ApproachTimeAux spaceModifies input?
Two-pointer in-placeO(n)O(1)Yes
Build new stringO(n)O(n)No
Python replace / join-splitO(n)O(n)No (new string)
C++ erase-remove_ifO(n)O(1)Yes

All four approaches visit each character exactly once, giving O(n) time. The space column is the deciding factor when memory is constrained. O(1) aux-space solutions (two-pointer, erase-remove) are preferred when the string is large and the input buffer can be reused safely.

Variations Worth Knowing

Remove only specific characters, not all spaces. Adjust the condition to target a particular character set:

# Remove underscores
result = s.replace('_', '')

# Remove multiple characters at once
s.translate(str.maketrans('', '', '_-'))

Remove all whitespace (tabs, newlines, carriage returns) in C. Use isspace() from <ctype.h> instead of checking against the literal space character:

#include <ctype.h>
#include <stdio.h>

void remove_all_whitespace(char *str) {
    int r = 0, w = 0;
    while (str[r] != '\0') {
        if (!isspace((unsigned char)str[r])) {
            str[w] = str[r];
            w++;
        }
        r++;
    }
    str[w] = '\0';
}

Casting to unsigned char before passing to isspace() is required on platforms where char is signed. If the character value is negative (common with extended ASCII above 127), passing it directly to isspace() produces undefined behaviour. The cast prevents this at zero runtime cost.

Placement judge constraint: O(1) space. If the problem statement says “do not use an additional array” or “modify the string in place,” the two-pointer approach is the expected answer. The replace-in-place pattern uses the same read/write-index technique for a different problem, so reviewing it alongside this one reinforces the general strategy.

The filter-and-write loop at the core of this problem appears in a wider range of contexts than it might seem. Text pre-processing pipelines use whitespace normalisation as a first pass before tokenisation. If you want to see how that step connects to LLM tokeniser logic in a working context, TinkerLLM builds the tokeniser from scratch as one of its early exercises. The entry price is ₹299, and the remove_spaces logic you just wrote is the first function that module calls.

Primary sources

Frequently asked questions

What is the difference between str.replace and join-split for removing spaces?

replace(' ', '') removes only ASCII space characters (code point 32). join(s.split()) splits on any whitespace — spaces, tabs, newlines — and joins the tokens without separator, so it handles multi-space gaps too. For placement judges that only test single spaces, both give identical output; for real text data, join-split is safer.

How do I remove spaces in C without using library functions?

Declare a write index (w = 0) and a read index (r). Loop r from 0 to strlen-1: if str[r] is not a space, copy str[r] to str[w] and increment w. After the loop, set str[w] to the null character. No library functions are needed beyond the null terminator assignment.

What is the time and space complexity of removing spaces from a string?

All three approaches run in O(n) time — every character is visited exactly once. Space complexity differs: the two-pointer in-place approach uses O(1) auxiliary space (just two index variables); building a new string or using library one-liners like replace() use O(n) auxiliary space for the output string.

Does Python's strip() remove all spaces from a string?

No. strip() removes leading and trailing whitespace only. It does not remove spaces in the middle of a string. Use replace(' ', '') to remove all spaces, or ''.join(s.split()) to remove all whitespace including tabs and newlines.

How do I remove only tabs and newlines but keep spaces in C?

Use isspace() from ctype.h but add a check to keep spaces: copy the character if it is either a space or not a whitespace character. In code: copy if c == ' ' or not isspace(c). Equivalently, skip only if isspace(c) and c is not a space.

Build AI projects

A self-paced playground for building with LLMs.

TinkerLLM is FACE Prep's sister property. A guided environment for shipping real LLM applications, the kind of project that earns a paragraph on your resume, not a line.

Try TinkerLLM (₹299 launch)
Free AI Roadmap PDF