Skip to content
← All posts

Number of Segments in a String: Counting Words Without Split

5 min read
leetcodeproblemeasystrings

LeetCode 434, Number of Segments in a String, asks you to count the number of segments in a string. A segment is a contiguous sequence of non-space characters. Given a string s, return how many segments it contains.

A few examples:

  • "Hello, my name is John" returns 5
  • "Hello" returns 1
  • "" returns 0

You might reach for split() and call len() on the result, but the real lesson here is recognizing that you can count segments in a single pass without building any intermediate list.

0123456789101112131415161718192021Hello,·my·name·is·Johnsegment 1segment 2segment 3segment 4segment 5segment characterspacetotal: 5 segments
The string "Hello, my name is John" contains 5 segments (words separated by spaces).

Why this problem matters

At first glance, counting words in a string seems trivial. And in Python, it nearly is: len(s.split()) gets the job done. But this problem is really about training your eye to spot transitions in sequential data. Instead of extracting words, you only need to detect where each word begins.

That skill, finding boundaries between states, shows up constantly in harder problems. Run-length encoding, parsing tokens, counting islands in a grid, and sliding window problems all rely on the same idea: something changes at position i, and you need to react to that change.

Solving this problem without split() builds the habit of scanning character by character and tracking state with minimal variables. It is a small investment that pays off when the same pattern appears in medium and hard problems where no built-in method can bail you out.

The approach

A segment starts whenever you see a non-space character that is either at position 0 or immediately follows a space. That is the only condition you need to check. Every time you find such a transition, increment a counter.

You do not need to find where each segment ends. You do not need to extract the words. You just need to count how many times a segment begins.

Walk through the string left to right. At each index i:

  1. If s[i] is a space, skip it.
  2. If s[i] is not a space and either i == 0 or s[i - 1] is a space, you have found the start of a new segment. Increment the count.
  3. If s[i] is not a space but s[i - 1] is also not a space, you are in the middle of an existing segment. Do nothing.
def countSegments(s: str) -> int:
    count = 0
    for i in range(len(s)):
        if s[i] != " " and (i == 0 or s[i - 1] == " "):
            count += 1
    return count

Step-by-step walkthrough

Here is the algorithm running on the string " foo bar ". Notice how the count only increases at the exact moment we transition from a space (or the start of the string) to a non-space character.

Step 1: Index 0

count = 0
·foo··bar·0123456789

Character is a space. We are not inside a segment. Count stays at 0.

Step 2: Index 1

count = 1
·foo··bar·0123456789

Character is 'f'. Previous character was a space, so this is a new segment. Count = 1.

Step 3: Index 2

count = 1
·foo··bar·0123456789

Character is 'o'. Still inside the same segment. Count stays at 1.

Step 4: Index 3

count = 1
·foo··bar·0123456789

Character is 'o'. Still inside the same segment. Count stays at 1.

Step 5: Index 4

count = 1
·foo··bar·0123456789

Character is a space. We leave the segment. Count stays at 1.

Step 6: Index 5

count = 1
·foo··bar·0123456789

Character is a space again. Still not in a segment. Count stays at 1.

Step 7: Index 6

count = 2
·foo··bar·0123456789

Character is 'b'. Previous character was a space, so this is a new segment. Count = 2.

Step 8: Index 7

count = 2
·foo··bar·0123456789

Character is 'a'. Still inside the same segment. Count stays at 2.

Step 9: Index 8

count = 2
·foo··bar·0123456789

Character is 'r'. Still inside the same segment. Count stays at 2.

Step 10: Index 9

count = 2
·foo··bar·0123456789

Character is a space. We leave the segment. Final count = 2.

The pointer visits each character exactly once. The count goes up at index 1 (the f after a leading space) and again at index 6 (the b after two spaces). The trailing space at index 9 does not trigger a new segment. Final answer: 2.

Complexity analysis

ApproachTimeSpace
One-pass transition countingO(n)O(1)
Split and countO(n)O(n)

The one-pass approach uses constant space because you only maintain a single integer counter. The split() approach allocates a list of word strings, which takes O(n) space in the worst case. Both run in O(n) time, but the manual scan avoids the overhead of creating intermediate strings.

Edge cases to watch for

  • Empty string. "" has length 0. The loop never executes, and the count stays at 0.
  • All spaces. " " contains no non-space characters, so no transition is ever detected. The count is 0.
  • No spaces at all. "hello" is a single segment. The condition triggers at index 0 because i == 0 and the character is not a space.
  • Leading and trailing spaces. " hello " has spaces on both ends. The algorithm skips the leading spaces, detects the segment at h, and ignores the trailing spaces. Count is 1.
  • Multiple spaces between words. "a b" has three spaces between two words. Only the transitions at a and b are counted. The extra spaces in between do not matter.

The building blocks

Boundary detection in sequences

The core technique here is detecting state transitions: the moment you cross from "space" to "non-space." This same idea powers problems like counting islands in a 1D array (transitioning from 0 to 1), run-length encoding (transitioning between different characters), and token parsing. Any time you need to count groups or detect boundaries, check whether the current element differs from the previous one.

Single-pass counting

Instead of building a data structure and then measuring it, you extract the answer during a single left-to-right scan. This pattern keeps space usage constant and is especially valuable when the input is a stream that you can only read once. Problems like Length of Last Word and majority element voting use the same principle: maintain a small amount of state and update it as you go.

From understanding to recall

You probably feel like you could solve this problem right now. But will you remember the exact condition, s[i] != " " and (i == 0 or s[i - 1] == " "), two weeks from now under interview pressure? The transition-detection pattern is simple but easy to get subtly wrong. You might check the wrong neighbor, forget the i == 0 boundary case, or accidentally count spaces instead of non-spaces.

Spaced repetition locks in the details. After a few reps spread across days, the boundary check becomes automatic. You stop thinking about whether to compare with s[i - 1] or s[i + 1] because the pattern is in muscle memory. And since this same technique applies to harder problems, the investment compounds.

Related posts