1. How would you count words in a string without libraries?
Count the words in a string without splitting the sentence or using regular expressions.
I would scan the string from left to right and keep a boolean called inWord. I start with count equal to 0 and inWord false. Whitespace sets inWord to false. When I see a non-whitespace character while inWord is false, I know a new word has started, so I increment count and set inWord to true. This counts each word exactly once. The time complexity is O(n), and the auxiliary space complexity is O(1).
See the Code while reading this explanation.
The goal is to count how many separate words appear in the string without splitting the sentence or using a regular expression. A word is a continuous run of non-whitespace characters. I read the characters from left to right and remember whether I am currently inside a word. I count a word only when I move from the start of the string or whitespace into a non-whitespace character. This avoids counting several letters from the same word more than once.
- Should spaces, tabs, and newlines all be treated as whitespace between words?
- Can the input be null, and if so, should it return 0?
The input is one string. The output is the number of words in that string. A word is a maximal continuous run of non-whitespace characters. We do not call split() and we do not use regular expressions. For the diagram example, s = "go to java", the answer is 3 because the words are "go", "to", and "java".
We only need two main variables. count stores how many word starts we have found. inWord tells us whether we are currently inside a word. The central rule is simple: increment count only when the current character is not whitespace and inWord is false.
Start with count = 0 because no words have been seen. Start with inWord = false because we are outside a word before reading the string. Traversal begins at index 0 and moves from left to right.
The exact string is "go to java", which has length 11. Its characters at indices 0 through 10 are g, o, space, space, t, o, space, j, a, v, a.
At index 0, the character is g. The state before processing it is inWord = false. It is not whitespace, so a new word starts. We increment count to 1 and set inWord = true.
At index 1, o is not whitespace and inWord is already true. It continues the same word, so count stays 1.
At index 2, the character is whitespace. We leave the current word by setting inWord = false. The count stays 1.
At index 3, there is another whitespace character. We are already outside a word, so inWord remains false and count remains 1.
At index 4, the character is t. Because inWord is false, this starts the second word. We increment count to 2 and set inWord = true.
At index 5, o continues the same word, so the count remains 2.
At index 6, whitespace ends the current word, so inWord becomes false.
At index 7, j is non-whitespace while inWord is false. It starts the third word. We increment count to 3 and set inWord = true.
At indices 8, 9, and 10, the characters a, v, and a continue the same word. The count stays 3. After the loop finishes, we return count = 3.
A word is counted exactly when a new non-whitespace run begins. Once we enter a word, inWord becomes true. This prevents later characters in that same word from increasing the count. When whitespace appears, inWord becomes false. The next non-whitespace character can then start another word. Therefore every word is counted exactly once.
The method first returns 0 for a null or empty string. It then initializes count = 0 and inWord = false. The loop reads one character at a time with charAt(i). Character.isWhitespace(c) detects whitespace such as spaces, tabs, and newlines. Whitespace sets inWord to false. A non-whitespace character increments count only when inWord was false. After all characters are processed, the method returns count.
If the string contains n characters, the algorithm examines each character once, so the time complexity is O(n). It uses only a fixed number of variables, so the auxiliary space complexity is O(1). Relevant edge cases are null or empty input, an all-whitespace string, multiple spaces between words, leading or trailing whitespace, and a string containing one word with no spaces.
The key insight is to count the start of each word instead of counting every non-whitespace character. The algorithm keeps a boolean state called inWord. The invariant is: after each processed character, count equals the number of word starts seen so far, and inWord tells whether we are currently inside a word. Whitespace sets inWord to false. A non-whitespace character increases count only when inWord is false. This makes every maximal non-whitespace run contribute exactly one to the result.
public class Main {
public static int countWords(String s) {
// A null or empty string contains no words.
if (s == null || s.isEmpty()) {
return 0;
}
// count stores how many word starts have been found so far.
int count = 0;
// inWord records whether the current processed position is inside a word.
boolean inWord = false;
// Process the string from left to right, one character at a time.
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// Whitespace ends the current word. This allows a later
// non-whitespace character to start and count a new word.
if (Character.isWhitespace(c)) {
inWord = false;
} else if (!inWord) {
// We are entering a new run of non-whitespace characters,
// so count this word exactly once.
count++;
inWord = true;
}
// Otherwise, c is another character in the current word.
// The state and count do not need to change.
}
// After every character is processed, count is the number of words.
return count;
}
public static void main(String[] args) {
// Exact example from the approved diagram. There are two spaces after "go".
String s = "go to java";
// The words are "go", "to", and "java", so the returned result is 3.
System.out.println(countWords(s));
}
}Let n be the number of characters in the string. The loop examines each character exactly once, so the time complexity is O(n). The extra memory does not grow with n. The algorithm only keeps variables such as count, inWord, the loop index, and the current character. Therefore the auxiliary space complexity is O(1).
This state-tracking pattern is useful when software processes text one character at a time and needs to detect boundaries between groups. For example, it can count whitespace-separated tokens without creating an array of substrings. The same idea is also useful for streaming text because the algorithm only needs the current character and a small amount of state.
This question tests whether you can solve a string-scanning problem with a small amount of state instead of relying on split() or regular expressions. The interviewer can evaluate whether you identify word boundaries correctly, maintain a useful invariant, handle repeated and leading or trailing whitespace, write clean Java, and explain why each word is counted exactly once. It also checks whether you can state the O(n) time and O(1) auxiliary space complexities correctly.
A common mistake is incrementing count for every non-whitespace character, which counts letters instead of words. Another mistake is forgetting to set inWord to false when whitespace appears. Candidates may also check only the literal space character and miss tabs or newlines, while the approved solution uses Character.isWhitespace(c). Consecutive spaces must not create extra words. Another mistake is using split() or a regular expression even though the question asks for direct character scanning.
Describe the algorithm as detecting the transition from outside a word to inside a word. Only that inWord = false to inWord = true transition increments the count, which makes the code and correctness argument easy to explain.









