2185. Counting Words With a Given Prefix
Problem Description
You are given an array of strings called words
and a string called pref
.
Your task is to count how many strings in the words
array have pref
as their prefix.
A prefix of a string is any leading contiguous substring that starts from the beginning of the string. For example:
- "app" is a prefix of "apple"
- "ban" is a prefix of "banana"
- "ca" is a prefix of "cat"
- Every string is a prefix of itself
The solution uses Python's built-in startswith()
method to check if each word in the array starts with the given prefix pref
. The sum()
function counts how many words satisfy this condition by treating True
as 1 and False
as 0.
For example:
- If
words = ["apple", "app", "apricot", "banana"]
andpref = "app"
, the function returns 2 because "apple" and "app" both start with "app" - If
words = ["pay", "attention", "practice", "attend"]
andpref = "at"
, the function returns 2 because "attention" and "attend" both start with "at"
Intuition
The problem asks us to count strings that have a specific prefix. The most straightforward approach is to check each word one by one to see if it starts with the given prefix.
When we think about checking if a string starts with another string, we're essentially comparing the first few characters. For a word to have pref
as its prefix, the first len(pref)
characters of the word must exactly match pref
.
Python provides a built-in method startswith()
that does exactly this check. Instead of manually comparing character by character or slicing strings, we can leverage this method for cleaner code.
The counting pattern here is simple: iterate through all words, check each one, and keep a counter. However, we can make this even more concise using Python's generator expression combined with sum()
. Since startswith()
returns a boolean (True
or False
), and Python treats True
as 1 and False
as 0 in numeric contexts, we can sum up all the boolean results directly to get our count.
The expression w.startswith(pref) for w in words
generates a sequence of boolean values, one for each word. When we apply sum()
to this sequence, it automatically counts how many True
values (words with the prefix) we have, giving us the final answer in a single line.
Solution Approach
The implementation uses a one-liner solution that combines Python's built-in functions for an elegant and efficient approach.
Step-by-step breakdown:
-
Iterate through the words array: We use a generator expression
for w in words
to go through each word in the input array. -
Check prefix condition: For each word
w
, we callw.startswith(pref)
which returns:True
if the word begins with the specified prefixFalse
otherwise
-
Count matching words: The
sum()
function aggregates the boolean results:- Each
True
is treated as 1 - Each
False
is treated as 0 - The sum gives us the total count of words with the prefix
- Each
Time Complexity: O(n * m)
where n
is the number of words and m
is the length of the prefix. For each word, the startswith()
method needs to compare up to m
characters.
Space Complexity: O(1)
as we only use a constant amount of extra space for the counter. The generator expression doesn't create an intermediate list.
The beauty of this solution lies in its simplicity - no explicit loops, no manual counter variables, and no conditional statements. The combination of sum()
with a generator expression that produces boolean values is a common Python pattern for counting items that satisfy a condition.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example to see how the solution works:
Input: words = ["coding", "code", "cool", "coffee"]
, pref = "co"
Step 1: We iterate through each word and check if it starts with "co":
-
"coding" → Check: Does "coding" start with "co"?
- Compare first 2 characters: "co" == "co" ✓
startswith()
returnsTrue
(counts as 1)
-
"code" → Check: Does "code" start with "co"?
- Compare first 2 characters: "co" == "co" ✓
startswith()
returnsTrue
(counts as 1)
-
"cool" → Check: Does "cool" start with "co"?
- Compare first 2 characters: "co" == "co" ✓
startswith()
returnsTrue
(counts as 1)
-
"coffee" → Check: Does "coffee" start with "co"?
- Compare first 2 characters: "co" == "co" ✓
startswith()
returnsTrue
(counts as 1)
Step 2: Sum up the results:
- Generator produces:
True, True, True, True
- In numeric context:
1 + 1 + 1 + 1
- Final sum:
4
Output: 4
All four words in the array have "co" as their prefix, so the function returns 4.
Let's trace through one more example where not all words match:
Input: words = ["cat", "car", "dog", "card"]
, pref = "ca"
- "cat" → starts with "ca" →
True
(1) - "car" → starts with "ca" →
True
(1) - "dog" → starts with "ca" →
False
(0) - "card" → starts with "ca" →
True
(1)
Sum: 1 + 1 + 0 + 1 = 3
Output: 3
Solution Implementation
1class Solution:
2 def prefixCount(self, words: List[str], pref: str) -> int:
3 """
4 Count the number of words that start with the given prefix.
5
6 Args:
7 words: List of strings to check
8 pref: The prefix string to match against
9
10 Returns:
11 Integer count of words that start with the prefix
12 """
13 # Use generator expression with sum to count matching words
14 # startswith() returns True (1) if word begins with prefix, False (0) otherwise
15 return sum(word.startswith(pref) for word in words)
16
1class Solution {
2 /**
3 * Counts the number of words in the array that start with the given prefix.
4 *
5 * @param words Array of strings to check
6 * @param pref The prefix string to match against
7 * @return The count of words that start with the prefix
8 */
9 public int prefixCount(String[] words, String pref) {
10 // Initialize counter for words with matching prefix
11 int count = 0;
12
13 // Iterate through each word in the array
14 for (String word : words) {
15 // Check if current word starts with the given prefix
16 if (word.startsWith(pref)) {
17 // Increment counter if prefix matches
18 count++;
19 }
20 }
21
22 // Return the total count of matching words
23 return count;
24 }
25}
26
1class Solution {
2public:
3 int prefixCount(vector<string>& words, string pref) {
4 // Initialize counter for words that start with the given prefix
5 int count = 0;
6
7 // Iterate through each word in the words vector
8 for (const auto& word : words) {
9 // Check if the word starts with the prefix
10 // find() returns 0 if pref is found at the beginning of word
11 if (word.find(pref) == 0) {
12 count++;
13 }
14 }
15
16 // Return the total count of words with the given prefix
17 return count;
18 }
19};
20
1/**
2 * Counts the number of words that start with the given prefix
3 * @param words - Array of strings to check
4 * @param pref - The prefix to search for
5 * @returns The count of words starting with the prefix
6 */
7function prefixCount(words: string[], pref: string): number {
8 // Use reduce to iterate through words and count matches
9 return words.reduce((count: number, word: string) => {
10 // Check if current word starts with the prefix
11 // If yes, increment count by 1, otherwise add 0
12 return count + (word.startsWith(pref) ? 1 : 0);
13 }, 0);
14}
15
Time and Space Complexity
Time Complexity: O(n * m)
where n
is the number of words in the list and m
is the length of the prefix pref
.
- The code iterates through each word in the
words
list once, which takesO(n)
iterations - For each word, the
startswith()
method needs to compare up tom
characters (the length of the prefix) to determine if the word starts withpref
- In the worst case, all comparisons need to check all
m
characters of the prefix - Therefore, the total time complexity is
O(n * m)
Space Complexity: O(1)
auxiliary space
- The
sum()
function with a generator expression processes elements one at a time without creating an intermediate list - The generator expression
(w.startswith(pref) for w in words)
yields Boolean values on-the-fly without storing them - Only a single counter variable is maintained internally by
sum()
to accumulate the count - The input lists themselves are not counted as they are given as input
- Therefore, the auxiliary space complexity is constant
O(1)
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Empty String Edge Cases
A common pitfall is not considering how empty strings behave with the startswith()
method:
- Every string (including empty strings) starts with an empty prefix
""
- An empty string
""
only has""
as its prefix
Example Issue:
words = ["", "hello", "world"] pref = "" # Returns 3 (all strings start with empty prefix) words = ["", "hello", "world"] pref = "h" # Empty string doesn't start with "h", returns 1
Solution: If your requirements differ from Python's default behavior (e.g., you want to exclude empty strings), add explicit validation:
def prefixCount(self, words: List[str], pref: str) -> int:
if not pref: # Handle empty prefix specially if needed
return len([w for w in words if w]) # Count non-empty words
return sum(word.startswith(pref) for word in words)
2. Case Sensitivity
The startswith()
method is case-sensitive, which might not match user expectations:
Example Issue:
words = ["Apple", "application", "APP"] pref = "app" # Returns 1 (only "application" matches)
Solution: Normalize the case if case-insensitive matching is required:
def prefixCount(self, words: List[str], pref: str) -> int:
pref_lower = pref.lower()
return sum(word.lower().startswith(pref_lower) for word in words)
3. Unicode and Special Characters
String comparison with special characters or different encodings can produce unexpected results:
Example Issue:
words = ["café", "cafe"] # Different Unicode representations pref = "caf" # May have inconsistent results depending on encoding
Solution: Normalize Unicode strings if dealing with international characters:
import unicodedata
def prefixCount(self, words: List[str], pref: str) -> int:
pref_normalized = unicodedata.normalize('NFC', pref)
return sum(
unicodedata.normalize('NFC', word).startswith(pref_normalized)
for word in words
)
4. Performance with Very Long Prefixes
While the solution is generally efficient, comparing very long prefixes against short words wastes cycles:
Example Issue:
words = ["a", "b", "c"] * 1000000 # Many short words pref = "extremely_long_prefix_that_cannot_possibly_match" # Still checks every character unnecessarily
Solution: Add an early length check optimization:
def prefixCount(self, words: List[str], pref: str) -> int:
pref_len = len(pref)
return sum(
len(word) >= pref_len and word.startswith(pref)
for word in words
)
Which of the following problems can be solved with backtracking (select multiple)
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!