Sometimes people repeat letters to represent extra feeling. For example:
"hello" -> "heeellooo""hi" -> "hiiii"In these strings like "heeellooo", we have groups of adjacent letters that are all the same: "h", "eee", "ll", "ooo".
You are given a string s and an array of query strings words. A query word is stretchy if it can be made to be equal to s by any number of applications of the following extension operation: choose a group consisting of characters c, and add some number of characters c to the group so that the size of the group is three or more.
"hello", we could do an extension on the group "o" to get "hellooo", but we cannot get "helloo" since the group "oo" has a size less than three. Also, we could do another extension like "ll" -> "lllll" to get "helllllooo". If s = "helllllooo", then the query word "hello" would be stretchy because of these two extension operations: query = "hello" -> "hellooo" -> "helllllooo" = s.Return the number of query strings that are stretchy.
Example 1:
Input: s = "heeellooo", words = ["hello", "hi", "helo"] Output: 1 Explanation: We can extend "e" and "o" in the word "hello" to get "heeellooo". We can't extend "helo" to get "heeellooo" because the group "ll" is not size 3 or more.
Example 2:
Input: s = "zzzzzyyyyy", words = ["zzyy","zy","zyy"] Output: 3
Constraints:
1 <= s.length, words.length <= 1001 <= words[i].length <= 100s and words[i] consist of lowercase letters.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The goal is to find how many words from a given list are considered 'expressive' versions of a target string. We'll do this by checking each word individually against the target string to see if it qualifies as an expressive word using brute force.
Here's how the algorithm would work step-by-step:
def expressive_words_brute_force(target_string, words):
expressive_count = 0
for word in words:
target_index = 0
word_index = 0
is_expressive = True
while word_index < len(word) and target_index < len(target_string):
if word[word_index] != target_string[target_index]:
is_expressive = False
break
word_char = word[word_index]
target_char = target_string[target_index]
word_char_count = 0
target_char_count = 0
# Count consecutive occurrences of the character
while word_index < len(word) and word[word_index] == word_char:
word_char_count += 1
word_index += 1
while target_index < len(target_string) and target_string[target_index] == target_char:
target_char_count += 1
target_index += 1
# Check for expressive conditions
if word_char_count > target_char_count:
is_expressive = False
break
# Target needs to have at least 3 if stretched
if target_char_count < 3 and word_char_count != target_char_count:
is_expressive = False
break
# Ensure both strings are exhausted
if word_index != len(word) or target_index != len(target_string):
is_expressive = False
# Increment the expressive count if expressive is True
if is_expressive:
expressive_count += 1
return expressive_countThe best way to solve this problem is to compare the target string and each word, character by character. The trick is to focus on the compressed form of each string, representing consecutive repeating characters as a count.
Here's how the algorithm would work step-by-step:
def expressive_words(target_string, words):
def get_compressed_string(input_string):
compressed = []
index = 0
while index < len(input_string):
character = input_string[index]
count = 0
while index < len(input_string) and input_string[index] == character:
count += 1
index += 1
compressed.append((character, count))
return compressed
compressed_target = get_compressed_string(target_string)
count_expressive_words = 0
for word in words:
compressed_word = get_compressed_string(word)
is_expressive = True
# Must compare compressed target and word
if len(compressed_target) != len(compressed_word):
continue
for i in range(len(compressed_target)):
target_character, target_count = compressed_target[i]
word_character, word_count = compressed_word[i]
if target_character != word_character:
is_expressive = False
break
# Target count must be >= word count
if target_count < word_count:
is_expressive = False
break
# Target count < 3 must be equal to word count
if target_count < 3 and target_count != word_count:
is_expressive = False
break
# Target count >= 3 must be >= word count
if target_count >= 3 and target_count < word_count:
is_expressive = False
break
if is_expressive:
count_expressive_words += 1
return count_expressive_words| Case | How to Handle |
|---|---|
| Null or empty string S | Return 0, as there are no expressive words if the base string is empty. |
| Null or empty words array | Return 0, as there are no words to check against S if the words array is empty. |
| Empty string S and empty words array | Return 0, as neither the source nor the target words exist. |
| String S with only one character | Handle words with a single character and lengths 1, 2, or 3 correctly according to the stretching rule. |
| Word in words longer than S | Such words can never be expressive, so they should be immediately skipped/counted as not expressive. |
| Large input strings S and words (performance) | Ensure that the character run length encoding and subsequent comparisons are done efficiently to avoid time limit exceeded errors; consider pre-processing the words. |
| String S with all the same character (e.g., 'aaaa') | Handle the stretching of single-character words to match S's length correctly, validating if count(word) <= count(S) and count(S) >= 3. |
| Word in words has characters not in S | Such words are automatically not expressive and should be immediately marked as such. |