Python 3.11+
The examples use standard Python containers and syntax available in the supported browser runtime; String itself is taught as an interview abstraction.
Verify in Python docs(opens in a new tab)Immutable character sequence used in parsing, matching, sliding-window, and dynamic-programming tasks. This guide turns that contract into deliberate Python operations, interview invariants, and a runnable practice loop.
Recognize it when
Consider String when the prompt's constraints and required operations match this shape: Immutable character sequence used in parsing, matching, sliding-window, and dynamic-programming tasks.

Sign in to save your code and progress across devices. The lesson and problem statement remain public.
A Python string is an immutable sequence of Unicode code points. An index identifies a position in that sequence, but no operation can replace a character in place. Every transformation must either reuse the original object or construct a new string. This ownership fact explains both the clean API and the hidden cost of careless concatenation.
For a scan, define what the processed prefix means. If count is the number of normalized vowels
in text[:index], reading text[index] extends that proof by exactly one character.
Indexing reads one character. A slice copies the selected range, so slicing k characters costs O(k)
time and space. Membership in a short fixed literal such as "aeiou" is bounded by that literal’s
size, while membership in a long string is linear in the searched text.
Normalization is part of the contract. lower() is often enough for an ASCII interview prompt;
casefold() is the stronger Unicode-oriented normalization. Neither operation mutates the source,
and both may allocate a new string.
def count_vowels(text):
vowels = set('aeiou')
return sum(character.casefold() in vowels for character in text)Implement count_vowels(text). Count ASCII vowels without changing the input, treating uppercase and lowercase letters equally.
Loading interactive editor.If it does not appear, the reference and starter code remain readable.Reload editor
Repeated result += piece can copy the growing prefix on each iteration. Accumulate pieces in a
list, then call "".join(parts) once. This makes the construction cost proportional to the total
output size rather than the sum of every intermediate prefix.
Use a list comprehension when each input produces one independent piece. Use an explicit loop when the next piece depends on parsing state, escaping, or a previous character.
def normalize_words(words):
parts = []
for word in words:
normalized = word.strip().lower()
if normalized:
parts.append(normalized)
return ' '.join(parts)Implement normalize_words(words). Strip and lowercase each non-empty word, then join the results with one space.
Loading interactive editor.If it does not appear, the reference and starter code remain readable.Reload editor
A delimiter alone is ambiguous when the original strings may contain that delimiter. A length
prefix makes the boundary self-describing: write the decimal length, a separator, then exactly that
many characters. During decoding, find the separator, parse the length, and advance by the stated
payload size. The invariant is that index always points at the beginning of the next length field.
def encode_strings(values):
return ''.join(f'{len(value)}#{value}' for value in values)
def decode_strings(payload):
values = []
index = 0
while index < len(payload):
separator = payload.index('#', index)
length = int(payload[index:separator])
start = separator + 1
end = start + length
values.append(payload[start:end])
index = end
return valuesImplement encode_strings(values) and decode_strings(payload) with decimal length prefixes followed by # and the exact string payload.
Loading interactive editor.If it does not appear, the reference and starter code remain readable.Reload editor
This approach handles empty strings and delimiter characters without escaping. Its work is linear in the encoded output size. Python string lengths count Unicode code points, which is consistent because the encoder and decoder use the same representation in the same runtime.
Use indices when you only need boundaries; taking a slice on every iteration adds copying. Use a list of characters when positions must be edited before producing the final string. Use a set or dictionary for repeated membership/count queries, and a sliding window when the answer concerns a contiguous substring whose state can be updated incrementally.
Do not sort merely to compare strings when a frequency table preserves all required information in linear time. Conversely, sorting can be the clearest canonical signature when the alphabet is not small and the additional O(k log k) work fits the constraints.
strip() without a specification can remove meaningful leading or trailing characters.text[left:right] can add quadratic copying.Say which unit the prompt calls a character, whether normalization is required, and whether indices or copied substrings are stored. While coding, state the prefix or parser-boundary invariant. When giving complexity, include every created slice and the size of the final output, not just the number of loop iterations.
Count Vowels(opens in a new tab) practices a normalized scan. Encode and Decode Strings(opens in a new tab) then tests whether the boundary contract survives empty values and payloads containing punctuation.
Python 3.11+
The examples use standard Python containers and syntax available in the supported browser runtime; String itself is taught as an interview abstraction.
Verify in Python docs(opens in a new tab)Interview bounds depend on the stated representation, input model, and real Python operations.
| Operation | Average | Worst | Interview note |
|---|---|---|---|
| Core String workflow | O(n) | O(n) | Lowercase each character and count membership in the five-vowel set. |
O(1) for the demonstrated String workflow.
These are the mistakes most likely to survive a happy-path example and fail a boundary case.
Placeholder code cannot preserve the String invariant or satisfy the public contract.
Prevent it: Implement the smallest complete transition and run the public tests before adding optimizations.
Avoid
def count_vowels(text):
passUse instead
def count_vowels(text):
return sum(character.lower() in 'aeiou' for character in text)Where you will hit this: Count Vowels(opens in a new tab)
This implementation ignores uppercase vowels and undercounts mixed-case input.
Prevent it: Keep this invariant visible while editing: State the precise String invariant before coding and preserve it after every update, traversal step, or recursive return.
Avoid
def count_vowels(text):
return sum(character in 'aeiou' for character in text)Use instead
def count_vowels(text):
return sum(character.lower() in 'aeiou' for character in text)Where you will hit this: Count Vowels(opens in a new tab)
Handle empty state, duplicate values, aliasing, and serialization boundaries explicitly in tests.
Prevent it: Account for every slice, copy, sort, membership test, and container mutation before claiming O(n).
Avoid
def count_vowels(text):
return sum(character in 'aeiou' for character in text)Use instead
def count_vowels(text):
return sum(character.lower() in 'aeiou' for character in text)Where you will hit this: Encode and Decode Strings(opens in a new tab)
Official Python documentation supports language behavior. Canonical problem pages provide additional practice context.
python-docs · checked 2026-07-12