Files
codetutor/backend/data/questions/check-if-word-occurs-as-prefix.yaml
2025-05-25 10:16:13 +01:00

162 lines
7.9 KiB
YAML

title: Check If a Word Occurs As a Prefix of Any Word in a Sentence
slug: check-if-word-occurs-as-prefix
difficulty: easy
leetcode_id: 1455
leetcode_url: https://leetcode.com/problems/check-if-a-word-occurs-as-a-prefix-of-any-word-in-a-sentence/
categories:
- strings
patterns:
- two-pointers
description: |
Given a `sentence` that consists of some words separated by a **single space**, and a `searchWord`, check if `searchWord` is a prefix of any word in `sentence`.
Return *the index of the word in* `sentence` *(**1-indexed**) where* `searchWord` *is a prefix of this word*. If `searchWord` is a prefix of more than one word, return the index of the first word **(minimum index)**. If there is no such word return `-1`.
A **prefix** of a string `s` is any leading contiguous substring of `s`.
constraints: |
- `1 <= sentence.length <= 100`
- `1 <= searchWord.length <= 10`
- `sentence` consists of lowercase English letters and spaces.
- `searchWord` consists of lowercase English letters.
examples:
- input: 'sentence = "i love eating burger", searchWord = "burg"'
output: "4"
explanation: '"burg" is prefix of "burger" which is the 4th word in the sentence.'
- input: 'sentence = "this problem is an easy problem", searchWord = "pro"'
output: "2"
explanation: '"pro" is prefix of "problem" which is the 2nd and the 6th word in the sentence, but we return 2 as it''s the minimal index.'
- input: 'sentence = "i am tired", searchWord = "you"'
output: "-1"
explanation: '"you" is not a prefix of any word in the sentence.'
explanation:
intuition: |
Think of the sentence as a sequence of words laid out in a row, like books on a shelf. You're looking for the first book whose title *starts with* a specific set of letters.
The key insight is that we don't need any fancy string matching algorithms here. The problem is straightforward: split the sentence into individual words, then check each word one by one to see if it begins with `searchWord`.
Since we want the **first** matching word, we iterate through the words in order and return immediately when we find a match. This "early return" pattern is efficient because we stop as soon as we find what we're looking for.
The prefix check itself is simple: a word has `searchWord` as a prefix if the first `len(searchWord)` characters of the word exactly match `searchWord`. Most languages provide a built-in `startswith()` or similar method for this.
approach: |
We solve this using a **Linear Scan with Prefix Check**:
**Step 1: Split the sentence into words**
- Use the space character as the delimiter to break the sentence into a list of words
- This gives us direct access to each word by index
&nbsp;
**Step 2: Iterate through words with their indices**
- For each word, check if it starts with `searchWord`
- Python's `str.startswith()` method handles the prefix comparison efficiently
- Remember the problem uses **1-indexed** positions, so we need to add 1 to the 0-based index
&nbsp;
**Step 3: Return the result**
- If a word matches, return its 1-indexed position immediately
- If no word matches after checking all, return `-1`
&nbsp;
This approach works because we process words in order, guaranteeing we find the minimum index first.
common_pitfalls:
- title: Off-by-One Error with 1-Indexing
description: |
The problem explicitly states that word positions are **1-indexed**, not 0-indexed. Many programming languages use 0-based indexing by default.
If you iterate with a loop like `for i in range(len(words))` and return `i` directly, you'll be off by one. The first word should return `1`, not `0`.
Always add 1 to convert from 0-indexed to 1-indexed, or use `enumerate(words, start=1)`.
wrong_approach: "Returning 0-indexed position directly"
correct_approach: "Add 1 to convert to 1-indexed position"
- title: Manual Prefix Checking Errors
description: |
If you implement prefix checking manually instead of using built-in methods, you might forget to check if the word is long enough.
For example, checking `word[:len(searchWord)] == searchWord` works, but manually comparing character-by-character without bounds checking could cause index out of range errors when the word is shorter than the search word.
Using `startswith()` handles all edge cases automatically.
wrong_approach: "Manual character comparison without length check"
correct_approach: "Use built-in startswith() or slice with length validation"
- title: Forgetting Empty String Edge Cases
description: |
While the constraints guarantee non-empty inputs, in a real interview you might encounter edge cases like empty sentences or empty search words.
An empty `searchWord` is technically a prefix of every word. Be prepared to discuss how you'd handle these cases if the constraints were relaxed.
key_takeaways:
- "**Use built-in methods**: `startswith()` is cleaner and handles edge cases better than manual prefix checking"
- "**Early return pattern**: Stop iterating as soon as you find the answer to avoid unnecessary work"
- "**Watch for indexing conventions**: Problems often specify 1-indexed results when natural language is involved"
- "**String splitting is your friend**: Converting a sentence to a word list simplifies iteration and access"
time_complexity: "O(n * m). We iterate through each character of the sentence once during split (O(n)), then for each word we may compare up to `m` characters where `m` is the length of `searchWord`. In the worst case, we check all words."
space_complexity: "O(n). We store the list of words after splitting, which in the worst case contains all characters from the original sentence."
solutions:
- approach_name: Linear Scan with startswith()
is_optimal: true
code: |
def is_prefix_of_word(sentence: str, search_word: str) -> int:
# Split sentence into list of words
words = sentence.split()
# Check each word (enumerate with start=1 for 1-indexed result)
for i, word in enumerate(words, start=1):
# If this word starts with searchWord, return its position
if word.startswith(search_word):
return i
# No word had the prefix
return -1
explanation: |
**Time Complexity:** O(n * m) — Where n is the sentence length and m is the search word length. Split is O(n), and each startswith check is O(m) in the worst case.
**Space Complexity:** O(n) — The words list stores all characters from the sentence.
This is the cleanest and most Pythonic solution. Using `enumerate` with `start=1` handles the 1-indexing requirement elegantly.
- approach_name: Manual Iteration Without Split
is_optimal: false
code: |
def is_prefix_of_word(sentence: str, search_word: str) -> int:
word_index = 1 # 1-indexed word counter
word_start = 0 # Start position of current word
i = 0
while i <= len(sentence):
# End of word: either space or end of sentence
if i == len(sentence) or sentence[i] == ' ':
# Extract current word
word = sentence[word_start:i]
# Check if searchWord is a prefix
if word.startswith(search_word):
return word_index
# Move to next word
word_index += 1
word_start = i + 1
i += 1
return -1
explanation: |
**Time Complexity:** O(n * m) — Same as the split approach.
**Space Complexity:** O(w) — Where w is the length of the longest word (for the substring extraction).
This approach avoids creating a list of all words upfront, potentially saving memory for very long sentences. However, it's more complex and the savings are negligible given the problem constraints.