311. Sparse Matrix Multiplication(有锁)【分治|循环】
2017/3/26 16:09:31
问题:求解稀疏矩阵乘法
版本1:朴素算法 θ(n3) 采用常规矩阵乘法公式
public static int[][] SparseMatrixMultiplication( int[][] A , int[][] B ){ int M = A.length; int N = B[0].length;//取列长 int K = A[0].length; int[][] C = new int[M][N]; for ( int i=0; i<M;i++ ) for ( int j=0;j<N;j++ ){ C[i][j] = 0; for ( int k=0;k<K;k++ ) C[i][j] += A[i][k] * B[k][j]; } return C; }
版本2:分治法 θ(n3) 利用分块矩阵乘法性质
public static void main(String[] args) { int[][] A = { {1,2,3},{4,5,6}}; int[][] B = { {1,2},{3,4},{5,6}}; int[][] C = SparseMatrixMultiplication(A, B); for ( int i=0;i<C.length;i++ ){ for ( int j=0;j<C[0].length;j++ ) System.out.print(C[i][j]+" "); System.out.println(); } } public static class Square{ public Square(int rowStart,int rowEnd,int colStart,int colEnd){ this.rowStart = rowStart; this.rowEnd = rowEnd; this.colStart = colStart; this.colEnd = colEnd; } int rowStart; int rowEnd; int colStart; int colEnd; } public static int[][] SparseMatrixMultiplication( int[][] A , int[][] B ){ Square a = new Square( 0 , A.length - 1 , 0 , A[0].length - 1); Square b = new Square( 0 , B.length - 1 , 0 , B[0].length - 1); return SparseMatrixMultiplicationHelper( A , B , a , b ); } public static int[][] MatrixSum( int[][] A , int[][] B){ int[][] C = new int[A.length][A[0].length]; for( int i=0;i<C.length;i++ ) for( int j=0;j<C[0].length;j++ ) C[i][j] = A[i][j] + B[i][j]; return C; } public static int[][] MatrixMerge( int[][] c11 , int[][] c12 , int[][] c21 ,int[][] c22){ int[][] C = new int[c11.length+c21.length][c11[0].length+c12[0].length]; for ( int i=0;i<c11.length;i++){ for( int j=0;j<c11[0].length;j++ ){ C[i][j] = c11[i][j]; } } for ( int i=0;i<c12.length;i++){ for( int j=0;j<c12[0].length;j++ ){ C[i][c11[0].length+j] = c12[i][j]; } } for ( int i=0;i<c21.length;i++){ for( int j=0;j<c11[0].length;j++ ){ C[c11.length+i][j] = c21[i][j]; } } for ( int i=0;i<c22.length;i++){ for( int j=0;j<c22[0].length;j++ ){ C[c11.length+i][c11[0].length+j] = c22[i][j]; } } return C; } public static int[][] SparseMatrixMultiplicationHelper( int[][] A , int[][] B ,Square a , Square b){ //递归基 int M = a.rowEnd - a.rowStart + 1 ; int N = b.colEnd - b.colStart + 1; int[][] C = new int[M][N]; if ( a.rowStart == a.rowEnd || a.colEnd == a.colStart || b.colStart == b.colEnd || b.rowStart == b.rowEnd ) { if ( a.rowStart == a.rowEnd && b.colStart == b.colEnd ){ for ( int i=0;i<b.rowEnd-b.rowStart+1;i++ ){ C[0][0] += A[a.rowStart][a.colStart+i] * B[b.rowStart+i][b.colStart]; } } else if ( a.colStart == a.colEnd && b.rowEnd == b.rowStart ){ for ( int i=0;i<a.rowEnd-a.rowStart+1;i++ ){ for ( int j=0;j<b.colEnd-b.colStart+1;j++){ C[i][j] = A[a.rowStart+i][a.colStart] * B[b.rowStart][b.colStart+j]; } } } return C; } Square a11 = new Square(a.rowStart , (a.rowEnd+a.rowStart)/2 , a.colStart , (a.colEnd+a.colStart)/2); Square a12 = new Square(a.rowStart , (a.rowEnd+a.rowStart)/2 , (a.colEnd+a.colStart)/2+1 , a.colEnd); Square a21 = new Square((a.rowEnd+a.rowStart)/2+1 , a.rowEnd , a.colStart , (a.colEnd+a.colStart)/2); Square a22 = new Square((a.rowEnd+a.rowStart)/2+1 , a.rowEnd , (a.colEnd+a.colStart)/2+1 , a.colEnd); Square b11 = new Square(b.rowStart , (b.rowEnd+b.rowStart)/2 , b.colStart , (b.colEnd+b.colStart)/2); Square b12 = new Square(b.rowStart , (b.rowEnd+b.rowStart)/2 , (b.colEnd+b.colStart)/2+1 , b.colEnd); Square b21 = new Square((b.rowEnd+b.rowStart)/2+1 , b.rowEnd , b.colStart , (b.colEnd+b.colStart)/2); Square b22 = new Square((b.rowEnd+b.rowStart)/2+1 , b.rowEnd , (b.colEnd+b.colStart)/2+1 , b.colEnd); int[][] c11 = MatrixSum(SparseMatrixMultiplicationHelper(A,B,a11,b11),SparseMatrixMultiplicationHelper(A,B,a12,b21)); int[][] c12 = MatrixSum(SparseMatrixMultiplicationHelper(A,B,a11,b12),SparseMatrixMultiplicationHelper(A,B,a12,b22)); int[][] c21 = MatrixSum(SparseMatrixMultiplicationHelper(A,B,a21,b11),SparseMatrixMultiplicationHelper(A,B,a22,b21)); int[][] c22 = MatrixSum(SparseMatrixMultiplicationHelper(A,B,a21,b12),SparseMatrixMultiplicationHelper(A,B,a22,b22)); C = MatrixMerge( c11, c12 ,c21 , c22); return C; }
版本3: 既然是稀疏矩阵,大部分元素是0,所以可以剪掉多余的乘法运算。A的某一行全为0或者B的某一列全为0都可以省略计算。
Python
class Solution(object): def multiply(self, A, B): if len(A)==0 or len(B)==0: return 0 m, n = len(A), len(B[0]) res = [ [0]*n for i in range(m) ] zerom, zeron = [True]*m, [True]*n for i in range(m): for index in range(len(A[0])): if A[i][index]!=0: zerom[i] = False break for i in range(n): for index in range(len(B)): if B[index][i]!=0: zeron[i] = False break for i in range(m): if zerom[i]==True: continue for j in range(n): if zeron[j]==True: continue for mul_ind in range(len(A[0])): res[i][j] += A[i][mul_ind] * B[mul_ind][j] return res