Implement a Sparse Matrix Class
PinterestMachine Learning Engineer · Technical ScreenLast updated
Design and implement a memory-efficient sparse matrix class supporting entry retrieval, updates, addition, and matrix multiplication.
Problem Statement
In machine learning recommendation systems, interaction datasets (such as users saving Pins) are represented by massive, highly sparse matrices. Storing these matrices as dense 2D arrays is infeasible due to memory limits.
Design and implement a SparseMatrix class that efficiently stores non-zero entries and performs basic linear algebra operations without iterating over zero elements.
Implement the following methods:
__init__(rows: int, cols: int): Initializes an empty matrix of dimensionsrows x cols.set(r: int, c: int, val: float) -> None: Sets the value at(r, c). Ifval == 0, the entry should not occupy memory.get(r: int, c: int) -> float: Returns the value at(r, c), or0.0if it is not set.add(other: SparseMatrix) -> SparseMatrix: Returns a newSparseMatrixrepresenting the sum ofselfandother. RaisesValueErrorif dimensions do not match.multiply(other: SparseMatrix) -> SparseMatrix: Returns a newSparseMatrixrepresenting the product ofselfandother. RaisesValueErrorifself.cols != other.rows.
Class Interface
class SparseMatrix:
def __init__(self, rows: int, cols: int):
pass
def set(self, r: int, c: int, val: float) -> None:
pass
def get(self, r: int, c: int) -> float:
pass
def add(self, other: 'SparseMatrix') -> 'SparseMatrix':
pass
def multiply(self, other: 'SparseMatrix') -> 'SparseMatrix':
pass
Constraints
1 <= rows, cols <= 100,000- Total non-zero entries per matrix
nnz <= 100,000 - Values are floating-point numbers.
- Operations must only iterate over non-zero values.
Examples
Example 1: Addition
A = SparseMatrix(2, 2)
A.set(0, 0, 1.0)
A.set(1, 1, 3.0)
B = SparseMatrix(2, 2)
B.set(0, 0, 4.0)
B.set(0, 1, 2.0)
C = A.add(B)
# C is a 2x2 matrix:
# [5.0, 2.0]
# [0.0, 3.0]
assert C.get(0, 0) == 5.0
assert C.get(0, 1) == 2.0
assert C.get(1, 1) == 3.0
assert C.get(1, 0) == 0.0
Example 2: Multiplication
A = SparseMatrix(2, 3)
A.set(0, 0, 1.0)
A.set(0, 2, 2.0)
B = SparseMatrix(3, 2)
B.set(0, 1, 3.0)
B.set(2, 1, 4.0)
C = A.multiply(B)
# Dimensions: 2x2
# Row 0 of A dot Col 1 of B: (1.0 * 3.0) + (2.0 * 4.0) = 11.0
assert C.get(0, 1) == 11.0
assert C.get(0, 0) == 0.0
Edge Cases
- Setting an existing non-zero value to
0.0should remove it from storage. - Two non-zero elements summing to
0.0during addition should not be stored in the result. - Multiplying matrices where no corresponding non-zero elements align should result in an empty sparse matrix.
Hints
Hint 1
Using a row-indexed hash map (e.g., mapping row index to a dictionary of `{col: val}`) makes finding matching column-row pairs during multiplication efficient.
Hint 2
For addition, copy non-zero entries from the first matrix into a new sparse matrix, then iterate over the non-zero entries of the second matrix, updating or removing entries if values cancel out.
Hint 3
For multiplication, instead of standard row-by-column dot products, iterate through non-zero entries `(i, k)` in matrix A, and then iterate through non-zero entries `(k, j)` in matrix B to accumulate into `C[i][j]`.
Follow-up questions
- How does a hash-map-based sparse matrix compare to Compressed Sparse Row (CSR) or Compressed Sparse Column (CSC) formats in terms of memory overhead and cache locality?
- How would you parallelize or distribute matrix multiplication across a cluster if neither matrix fits in a single machine's RAM?
- Because floating-point arithmetic can introduce small rounding errors (e.g., `1e-9`), how would you handle values near zero when deciding whether an element is non-zero?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.