From 9794fef14452d8fa10943fb51e024462b2d9650b Mon Sep 17 00:00:00 2001 From: anebz Date: Wed, 3 Apr 2019 19:05:41 +0200 Subject: [PATCH] 1.8. zero matrix --- .../1.8. zero_matrix.java | 107 ++++++++++++++++++ .../1.8. zero_matrix.md | 74 ++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 Chapter 1 Arrays and strings/1.8. zero_matrix.java create mode 100644 Chapter 1 Arrays and strings/1.8. zero_matrix.md diff --git a/Chapter 1 Arrays and strings/1.8. zero_matrix.java b/Chapter 1 Arrays and strings/1.8. zero_matrix.java new file mode 100644 index 0000000..b9cf03c --- /dev/null +++ b/Chapter 1 Arrays and strings/1.8. zero_matrix.java @@ -0,0 +1,107 @@ +public class QuestionB { + public static void nullifyRow(int[][] matrix, int row) { + for (int j = 0; j < matrix[0].length; j++) { + matrix[row][j] = 0; + } + } + + public static void nullifyColumn(int[][] matrix, int col) { + for (int i = 0; i < matrix.length; i++) { + matrix[i][col] = 0; + } + } + + public static void setZeros(int[][] matrix) { + boolean rowHasZero = false; + boolean colHasZero = false; + + // Check if first row has a zero + for (int j = 0; j < matrix[0].length; j++) { + if (matrix[0][j] == 0) { + rowHasZero = true; + break; + } + } + + // Check if first column has a zero + for (int i = 0; i < matrix.length; i++) { + if (matrix[i][0] == 0) { + colHasZero = true; + break; + } + } + + // Check for zeros in the rest of the array + for (int i = 1; i < matrix.length; i++) { + for (int j = 1; j < matrix[0].length;j++) { + if (matrix[i][j] == 0) { + matrix[i][0] = 0; + matrix[0][j] = 0; + } + } + } + + // Nullify rows based on values in first column + for (int i = 1; i < matrix.length; i++) { + if (matrix[i][0] == 0) { + nullifyRow(matrix, i); + } + } + + // Nullify columns based on values in first row + for (int j = 1; j < matrix[0].length; j++) { + if (matrix[0][j] == 0) { + nullifyColumn(matrix, j); + } + } + + // Nullify first row + if (rowHasZero) { + nullifyRow(matrix, 0); + } + + // Nullify first column + if (colHasZero) { + nullifyColumn(matrix, 0); + } + } + + public static boolean matricesAreEqual(int[][] m1, int[][] m2) { + if (m1.length != m2.length || m1[0].length != m2[0].length) { + return false; + } + + for (int k = 0; k < m1.length; k++) { + for (int j = 0; j < m1[0].length; j++) { + if (m1[k][j] != m2[k][j]) { + return false; + } + } + } + return true; + } + + public static int[][] cloneMatrix(int[][] matrix) { + int[][] c = new int[matrix.length][matrix[0].length]; + for (int i = 0; i < matrix.length; i++) { + for (int j = 0; j < matrix[0].length; j++) { + c[i][j] = matrix[i][j]; + } + } + return c; + } + + public static void main(String[] args) { + int nrows = 10; + int ncols = 15; + int[][] matrix = AssortedMethods.randomMatrix(nrows, ncols, -10, 10); + + AssortedMethods.printMatrix(matrix); + + setZeros(matrix); + + System.out.println(); + + AssortedMethods.printMatrix(matrix); + } +} \ No newline at end of file diff --git a/Chapter 1 Arrays and strings/1.8. zero_matrix.md b/Chapter 1 Arrays and strings/1.8. zero_matrix.md new file mode 100644 index 0000000..963ebf6 --- /dev/null +++ b/Chapter 1 Arrays and strings/1.8. zero_matrix.md @@ -0,0 +1,74 @@ +# 1.8. Zero matrix + +## Given an M x N matrix, if an element is 0, make the entire row and column 0 + +> Example: + +```python +imat = [[1,2,0,9], + [4,0,6,8], + [7,8,9,1]] + +omat = [[0,0,0,0], + [0,0,0,0], + [7,0,0,1]] +``` + +## First idea + +Intuitivelly I'd find all initial 0 elements, and then 0-ize the respective rows and cols. Only initial 0s must be 0-ized, not new ones. If I have to save all initial zeroes, that's already O(NM). Then iterate through all 0s again, and 0-ize. Which in turn takes O(k(N+M)). If there's a 0 in all rows/cols, the whole matrix is 0 and we can break the loop. + +## Hints + +1. Find all zeroes first, got it +2. Use O(M+N) space instead of O(NM)? What info do you really need from the list of zeroes? + +> example: + +```python +list_zeroes = [(0,2), (1,1)] +``` + +The only info we need is which rows and cols are 'touched', in this case rows:0,1, cols:1,2. Then just go to those rows and delete all cols, and go to all cols and delete all rows. + +```python +rows = [] +cols = [] +for i in range(M): + for j in range(N): + if len(rows) == M or len(cols) == N: + return 0 # zero matrix + if imat[i][j] == 0: + if i not in rows: + rows.append(i) + if j not in cols: + cols.append(j) + +for r in rows: + for j in range(N): + imat[r][j] = 0 + +for c in cols: + for i in range(N): + imat[i][c] = 0 + +return imat +``` + +If all rows or all cols are represented, the whole matrix becomes 0. + +## Third hint + +Reduce additional storage of 0s by using the matrix itself for data storage? In my implementation, space complexity it at most O(M+N) but no idea how to 'flag' these 0es in the matrix itself... + +## Solution + +Use two arrays to keep track of all the rows with zeros and all the columns with zeros, and then nullify rows and columns based on the values in these arrays. The two arrays are boolean arrays of length N and length M. + +Use a bit vector instead of boolean arrays. We can reduce the space to O(1) by using the first column as a replacement for the `row` array and the first row as a replacement for the `column` array. + +1. Check if the first row and first column have any zeroes, and set variables `rowHasZero` and `columnHasZero` +2. Iterate through the rest of the matrix, setting imat[i][0] and imat[0][j] to zero whenever there's a zero in imat[i][j]. +3. Iterate through the rest of matrix, nullifying row `i` if there's a zero in `imat[i][0]` +4. Iterate through the rest of matrix, nullifying col `j` if there's a zero in `imat[0][j]` +5. Nullify the first row and first column if necessary, based on values from step1. \ No newline at end of file