Facebook Pixel

2185. Counting Words With a Given Prefix

EasyArrayStringString Matching
Leetcode Link

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"] and pref = "app", the function returns 2 because "apple" and "app" both start with "app"
  • If words = ["pay", "attention", "practice", "attend"] and pref = "at", the function returns 2 because "attention" and "attend" both start with "at"
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

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:

  1. Iterate through the words array: We use a generator expression for w in words to go through each word in the input array.

  2. Check prefix condition: For each word w, we call w.startswith(pref) which returns:

    • True if the word begins with the specified prefix
    • False otherwise
  3. 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

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 Evaluator

Example 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() returns True (counts as 1)
  • "code" → Check: Does "code" start with "co"?

    • Compare first 2 characters: "co" == "co" ✓
    • startswith() returns True (counts as 1)
  • "cool" → Check: Does "cool" start with "co"?

    • Compare first 2 characters: "co" == "co" ✓
    • startswith() returns True (counts as 1)
  • "coffee" → Check: Does "coffee" start with "co"?

    • Compare first 2 characters: "co" == "co" ✓
    • startswith() returns True (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 takes O(n) iterations
  • For each word, the startswith() method needs to compare up to m characters (the length of the prefix) to determine if the word starts with pref
  • 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
    )
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Which of the following problems can be solved with backtracking (select multiple)


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More