I went with a dict-of-dicts internally, rows as outer keys and columns as inner.
Start by clarifying requirements and constraints, then propose a memory-efficient representation like a dictionary of keys (DOK) or compressed sparse row (CSR). Walk through the algorithms for addition and multiplication, emphasizing dimension validation and error handling, and discuss trade-offs between different sparse formats.
Pro tip: Mention that for addition, you can iterate over the union of keys, and for multiplication, you can optimize by iterating over the smaller matrix's non-zero entries and checking compatibility. Also, highlight that raising meaningful errors early (e.g., ValueError with clear messages) is crucial for usability.
Ask about expected matrix sizes, sparsity levels, operations frequency, and whether the matrices are immutable. This informs the choice of representation and algorithms.
Propose a dictionary of keys (DOK) mapping (row, col) to value, or compressed sparse row (CSR) for efficient row access. Discuss trade-offs: DOK is simple and good for incremental construction, CSR is efficient for arithmetic but complex to build.
Check that both matrices have the same shape; if not, raise ValueError with a clear message. Iterate over the union of non-zero keys, summing values and omitting zeros to maintain sparsity.
Check that the number of columns of the first matrix equals the number of rows of the second; if not, raise ValueError. Use an efficient algorithm: for each non-zero in the first matrix, iterate over non-zeros in the corresponding row of the second matrix, accumulating results.
Ensure meaningful errors for incompatible shapes, handle empty matrices, and consider zero elimination after operations. Mention that operations should return new sparse matrices, not modify inputs.
AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.