Welcome to Subscribe On Youtube

311. Sparse Matrix Multiplication

Description

Given two sparse matrices mat1 of size m x k and mat2 of size k x n, return the result of mat1 x mat2. You may assume that multiplication is always possible.

 

Example 1:

Input: mat1 = [[1,0,0],[-1,0,3]], mat2 = [[7,0,0],[0,0,0],[0,0,1]]
Output: [[7,0,0],[-7,0,3]]

Example 2:

Input: mat1 = [[0]], mat2 = [[0]]
Output: [[0]]

 

Constraints:

  • m == mat1.length
  • k == mat1[i].length == mat2.length
  • n == mat2[i].length
  • 1 <= m, n, k <= 100
  • -100 <= mat1[i][j], mat2[i][j] <= 100

Solutions

Solution 1: Direct Multiplication

We can directly calculate each element in the result matrix according to the definition of matrix multiplication.

The time complexity is $O(m \times n \times k)$, and the space complexity is $O(m \times n)$. Where $m$ and $n$ are the number of rows of matrix $mat1$ and the number of columns of matrix $mat2$ respectively, and $k$ is the number of columns of matrix $mat1$ or the number of rows of matrix $mat2$.

Solution 2: Preprocessing

We can preprocess the sparse representation of the two matrices, i.e., $g1[i]$ represents the column index and value of all non-zero elements in the $i$th row of matrix $mat1$, and $g2[i]$ represents the column index and value of all non-zero elements in the $i$th row of matrix $mat2$.

Next, we traverse each row $i$, traverse each element $(k, x)$ in $g1[i]$, traverse each element $(j, y)$ in $g2[k]$, then $mat1[i][k] \times mat2[k][j]$ will correspond to $ans[i][j]$ in the result matrix, and we can accumulate all the results.

The time complexity is $O(m \times n \times k)$, and the space complexity is $O(m \times n)$. Where $m$ and $n$ are the number of rows of matrix $mat1$ and the number of columns of matrix $mat2$ respectively, and $k$ is the number of columns of matrix $mat1$ or the number of rows of matrix $mat2$.

  • class Solution {
        public int[][] multiply(int[][] mat1, int[][] mat2) {
            int m = mat1.length, n = mat2[0].length;
            int[][] ans = new int[m][n];
            var g1 = f(mat1);
            var g2 = f(mat2);
            for (int i = 0; i < m; ++i) {
                for (int[] p : g1[i]) {
                    int k = p[0], x = p[1];
                    for (int[] q : g2[k]) {
                        int j = q[0], y = q[1];
                        ans[i][j] += x * y;
                    }
                }
            }
            return ans;
        }
    
        private List<int[]>[] f(int[][] mat) {
            int m = mat.length, n = mat[0].length;
            List<int[]>[] g = new List[m];
            Arrays.setAll(g, i -> new ArrayList<>());
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (mat[i][j] != 0) {
                        g[i].add(new int[] {j, mat[i][j]});
                    }
                }
            }
            return g;
        }
    }
    
  • class Solution {
    public:
        vector<vector<int>> multiply(vector<vector<int>>& mat1, vector<vector<int>>& mat2) {
            int m = mat1.size(), n = mat2[0].size();
            vector<vector<int>> ans(m, vector<int>(n));
            auto g1 = f(mat1), g2 = f(mat2);
            for (int i = 0; i < m; ++i) {
                for (auto& [k, x] : g1[i]) {
                    for (auto& [j, y] : g2[k]) {
                        ans[i][j] += x * y;
                    }
                }
            }
            return ans;
        }
    
        vector<vector<pair<int, int>>> f(vector<vector<int>>& mat) {
            int m = mat.size(), n = mat[0].size();
            vector<vector<pair<int, int>>> g(m);
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (mat[i][j]) {
                        g[i].emplace_back(j, mat[i][j]);
                    }
                }
            }
            return g;
        }
    };
    
  • class Solution:
        def multiply(self, mat1: List[List[int]], mat2: List[List[int]]) -> List[List[int]]:
            def f(mat: List[List[int]]) -> List[List[int]]:
                g = [[] for _ in range(len(mat))]
                for i, row in enumerate(mat):
                    for j, x in enumerate(row):
                        if x:
                            g[i].append((j, x))
                return g
    
            g1 = f(mat1)
            g2 = f(mat2)
            m, n = len(mat1), len(mat2[0])
            ans = [[0] * n for _ in range(m)]
            for i in range(m):
                for k, x in g1[i]:
                    for j, y in g2[k]:
                        ans[i][j] += x * y
            return ans
    
    
  • func multiply(mat1 [][]int, mat2 [][]int) [][]int {
    	m, n := len(mat1), len(mat2[0])
    	ans := make([][]int, m)
    	for i := range ans {
    		ans[i] = make([]int, n)
    	}
    	f := func(mat [][]int) [][][2]int {
    		m, n := len(mat), len(mat[0])
    		g := make([][][2]int, m)
    		for i := range g {
    			g[i] = make([][2]int, 0, n)
    			for j := range mat[i] {
    				if mat[i][j] != 0 {
    					g[i] = append(g[i], [2]int{j, mat[i][j]})
    				}
    			}
    		}
    		return g
    	}
    	g1, g2 := f(mat1), f(mat2)
    	for i := range g1 {
    		for _, p := range g1[i] {
    			k, x := p[0], p[1]
    			for _, q := range g2[k] {
    				j, y := q[0], q[1]
    				ans[i][j] += x * y
    			}
    		}
    	}
    	return ans
    }
    
  • function multiply(mat1: number[][], mat2: number[][]): number[][] {
        const [m, n] = [mat1.length, mat2[0].length];
        const ans: number[][] = Array.from({ length: m }, () => Array.from({ length: n }, () => 0));
        const f = (mat: number[][]): number[][][] => {
            const [m, n] = [mat.length, mat[0].length];
            const ans: number[][][] = Array.from({ length: m }, () => []);
            for (let i = 0; i < m; ++i) {
                for (let j = 0; j < n; ++j) {
                    if (mat[i][j] !== 0) {
                        ans[i].push([j, mat[i][j]]);
                    }
                }
            }
            return ans;
        };
        const g1 = f(mat1);
        const g2 = f(mat2);
        for (let i = 0; i < m; ++i) {
            for (const [k, x] of g1[i]) {
                for (const [j, y] of g2[k]) {
                    ans[i][j] += x * y;
                }
            }
        }
        return ans;
    }
    
    

All Problems

All Solutions