| layout | default |
|---|---|
| title | Interview Problems |
| parent | Practice and Projects |
| nav_order | 3 |
| permalink | /practice/interview-problems/ |
Complete these after the numbered lessons. In an interview, explain the input, edge cases, plan, and trade-offs before writing code. A readable correct solution is better than a clever unfinished one.
- Group order records by customer while preserving the original order.
- Flatten a nested list whose depth is not known in advance.
- Build a fixed-capacity least-recently-used cache.
- Write a retry decorator with a maximum attempt count and injectable delay function.
- Create an iterator that reads valid records from a large text file.
- Merge several already-sorted iterables without loading every value at once.
- Design a repository interface and SQLite implementation for a task service.
- Test a notification service without sending a real email.
- Parse an API response while reporting missing and invalid fields clearly.
- Process many files concurrently and return successes and failures in input order.
- Detect repeated words in text with punctuation and mixed letter case.
- Design a command-line tool with subcommands and meaningful exit codes.
- Explain and fix a circular import between two modules.
- Compare a list comprehension, generator expression, and normal loop for one task.
- Investigate a race condition in a shared counter and redesign the communication.
Show hints
- A dictionary can map each customer to a list.
- Decide whether strings count as nested collections; recursion or an explicit stack can help.
- Combine a key lookup with a structure that records recent use.
- The wrapper needs
*args,**kwargs, a loop, and a narrow exception policy. - Open the file in a generator and
yieldone validated record. - Study a heap or
heapq.merge()after writing a two-iterable version. - Keep business rules independent of SQL details.
- Inject an object with a
send()method and record its calls. - Separate transport failure, JSON decoding, shape validation, and field conversion.
- Associate each future with its input position.
- Normalize case and define what counts as a word.
- Let each subparser select a handler function.
- Move shared definitions, delay an import, or redesign module responsibilities.
- Compare readability, eager memory use, and one-time iteration.
- Do not assume a compound read-modify-write operation is one safe step.
Show solution directions
- Use
setdefault()ordefaultdict(list)and append each record. - Recursively yield nested values while treating strings as atomic values.
- Use a dictionary plus
OrderedDict, or explain why a custom doubly linked list gives constant-time updates. - Use
functools.wraps; retry only expected temporary exceptions and re-raise the final one. - Put
with open(...)inside the generator function so iteration controls its lifetime. heapq.merge()provides a lazy standard-library implementation.- Define small repository operations, inject the repository into the service, and parameterize every query.
- A fake sender stores messages in a list that the test can inspect.
- Raise or return distinct domain errors for each boundary instead of one vague failure.
- Store index-to-result mappings and assemble the final list after all futures finish.
- Use a suitable regular expression or explicit character normalization, then count with a dictionary.
- Use
argparsesubparsers and amain(arguments) -> intfunction. - Extract common types into a third module when both original modules truly need them.
- Choose based on intent: a list for reuse, a generator for streaming, and a loop for complex branching.
- Protect the update with a lock or avoid shared updates by returning partial counts and reducing them.
For every answer, test empty input, one item, duplicate values, malformed input, and a larger case. State approximate time and memory growth in plain language, then identify one alternative design and its trade-off.