Python 3.11+
The examples use standard Python containers and syntax available in the supported browser runtime; Array itself is taught as an interview abstraction.
Verify in Python docs(opens in a new tab)Contiguous indexed sequence used for random access, scanning, and in-place transformations. This guide turns that contract into deliberate Python operations, interview invariants, and a runnable practice loop.
Recognize it when
Consider Array when the prompt's constraints and required operations match this shape: Contiguous indexed sequence used for random access, scanning, and in-place transformations.

Sign in to save your code and progress across devices. The lesson and problem statement remain public.
An interview “array” in Python is usually a list: an ordered sequence whose integer indices form
a dense range from zero through len(values) - 1. Treat the index as part of the data model. A
loop invariant should say what the processed prefix means, not merely that a loop counter moved.
For example, after processing values[:right], a result array might contain the answer for exactly
those positions. That statement makes an off-by-one error visible: either right is already
processed or it is the next position, but it cannot be both.
Python lists hold references to objects. Assignment creates another name for the same list; it does not copy the elements. A shallow copy creates a new outer list but still shares nested objects. In an interview, say whether the function may mutate its input before using an in-place technique.
The Python list documentation(opens in a new tab) defines the operations. Index reads and writes are constant-time operations. Appending is amortized O(1), while inserting or deleting near the front shifts later references and therefore costs O(n).
def replace_at(values, index, item):
previous = values[index]
values[index] = item
return previousImplement replace_at(values, index, item). Return the previous item and mutate exactly the requested list position without changing its length.
Loading interactive editor.If it does not appear, the reference and starter code remain readable.Reload editor
Choose the operation whose cost matches the proof:
| Operation | Time | Ownership effect |
|---|---|---|
values[index] |
O(1) | Reads the existing object reference |
values[index] = item |
O(1) | Mutates the original list through every alias |
values.append(item) |
Amortized O(1) | Mutates the original list |
values.insert(0, item) |
O(n) | Shifts every existing reference |
values[start:end] |
O(k) | Allocates a new outer list of k references |
values.copy() |
O(n) | Allocates a shallow outer copy |
Slicing inside a loop can turn a linear-looking solution into quadratic work. Repeatedly creating
values[:right] copies a growing prefix; prefer indices or a maintained aggregate when the
algorithm only needs a boundary.
def changed_copy(values, index, item):
result = values.copy()
result[index] = item
return resultImplement changed_copy(values, index, item). Return a shallow outer copy with one replacement while leaving the original list unchanged.
Loading interactive editor.If it does not appear, the reference and starter code remain readable.Reload editor
When values come from a known dense domain, a list can replace a hash lookup. If every value is in
1..n, index value - 1 is a collision-free location for that label. The invariant is precise:
after scanning a prefix, seen[i] is true exactly when i + 1 occurred in that prefix. A duplicate
sets the same boolean again; it must not toggle the bit back to false.
def mark_seen_indices(values):
seen = [False] * len(values)
for value in values:
seen[value - 1] = True
return seenImplement mark_seen_indices(values). Values are integers from 1 through len(values). Return a boolean list whose index i is true exactly when i + 1 occurs.
Loading interactive editor.If it does not appear, the reference and starter code remain readable.Reload editor
Use a list when positions are dense, order matters, and indexed access or mutation dominates. Use a dictionary instead when keys are sparse or not integers. Use a deque rather than a list when the hot operation removes from the front. Use a set when only membership matters and no positional answer is required.
Sorting may expose useful order, but it changes positions and costs O(n log n). Before sorting, check whether the required answer includes original indices or whether a one-pass hash map preserves the needed information more directly.
matrix = [[0] * columns] * rows aliases the same inner list; use a comprehension to allocate
independent rows.if target in values is O(n), not O(1); placing it inside a scan can produce O(n squared) work.values = values + [item] allocates a new list, while append mutates the existing list.-1 can return a plausible but wrong value.Before coding, state: “I will use the index as the stable identity of each position, and after each iteration the processed prefix has its final result.” While coding, call out whether the list is an input you may mutate, a fixed-size output buffer, or auxiliary state. At the end, count every full scan, slice, sort, insertion shift, and allocated list before giving time and space bounds.
The focused Mark Seen Indices(opens in a new tab) drill practices direct domain-to-index mapping. Product Except Self(opens in a new tab) then requires two directional invariants over the same dense positions without hiding an extra division or nested scan.
Python 3.11+
The examples use standard Python containers and syntax available in the supported browser runtime; Array 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 Array workflow | O(n) | O(n) | A bounded 1..n value domain can map directly into n array positions without a dictionary key lookup. After reading a value v, result[v - 1] is true and every previously marked position stays true. |
O(n) for the demonstrated Array workflow.
These are the mistakes most likely to survive a happy-path example and fail a boundary case.
Placeholder code cannot preserve the Array invariant or satisfy the public contract.
Prevent it: Implement the smallest complete transition and run the public tests before adding optimizations.
Avoid
def mark_seen_indices(values):
passUse instead
def mark_seen_indices(values):
seen = [False] * len(values)
for value in values:
seen[value - 1] = True
return seenWhere you will hit this: Mark Seen Indices(opens in a new tab)
Toggles each mapped position, causing an even number of duplicate occurrences to look absent.
Prevent it: Keep this invariant visible while editing: State the precise Array invariant before coding and preserve it after every update, traversal step, or recursive return.
Avoid
def mark_seen_indices(values):
seen = [False] * len(values)
for value in values:
seen[value - 1] = not seen[value - 1]
return seenUse instead
def mark_seen_indices(values):
seen = [False] * len(values)
for value in values:
seen[value - 1] = True
return seenWhere you will hit this: Mark Seen Indices(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 mark_seen_indices(values):
seen = [False] * len(values)
for value in values:
seen[value - 1] = not seen[value - 1]
return seenUse instead
def mark_seen_indices(values):
seen = [False] * len(values)
for value in values:
seen[value - 1] = True
return seenWhere you will hit this: Product Except Self(opens in a new tab)
Official Python documentation supports language behavior. Canonical problem pages provide additional practice context.
python-docs · checked 2026-07-27