|
| 1 | +# 01 Matrix |
| 2 | + |
| 3 | +Page on leetcode: https://leetcode.com/problems/01-matrix/ |
| 4 | + |
| 5 | +## Problem Statement |
| 6 | + |
| 7 | +Given an m x n binary matrix mat, return the distance of the nearest 0 for each cell. |
| 8 | + |
| 9 | +The distance between two adjacent cells is 1. |
| 10 | + |
| 11 | +### Constraints |
| 12 | + |
| 13 | +- m == mat.length |
| 14 | +- n == mat[i].length |
| 15 | +- 1 <= m, n <= 104 |
| 16 | +- 1 <= m \* n <= 104 |
| 17 | +- mat[i][j] is either 0 or 1. |
| 18 | +- There is at least one 0 in mat. |
| 19 | + |
| 20 | +### Example |
| 21 | + |
| 22 | +``` |
| 23 | +Input: mat = [[0,0,0],[0,1,0],[0,0,0]] |
| 24 | +Output: [[0,0,0],[0,1,0],[0,0,0]] |
| 25 | +``` |
| 26 | + |
| 27 | +``` |
| 28 | +Input: mat = [[0,0,0],[0,1,0],[1,1,1]] |
| 29 | +Output: [[0,0,0],[0,1,0],[1,2,1]] |
| 30 | +``` |
| 31 | + |
| 32 | +## Solution |
| 33 | + |
| 34 | +- No diagonal travel allowed |
| 35 | +- If cell is already 0 it stays 0? |
| 36 | +- BFS search, if any surrounding are 0 cell stays 1 |
| 37 | +- flag to show that cell has been searched? |
| 38 | +- If I could find the 0 and work outwards from there that would be ideal |
| 39 | + |
| 40 | +### Initial Pseudocode |
| 41 | + |
| 42 | +If you find a zero, set current value to 1, update other three directions to 2 |
| 43 | +If you don't find a zero, update current value + 1, update parent to curr + 1 |
| 44 | + |
| 45 | +### Optimized Solution |
| 46 | + |
| 47 | +There are a couple of ways to approach the problem. One is with Breadth First Search and the other is with Dynamic Programming. You can see a discussion of the two approached here: https://leetcode.com/problems/01-matrix/discuss/1369741/C%2B%2BJavaPython-BFS-DP-solutions-with-Picture-Clean-and-Concise-O(1)-Space |
| 48 | + |
| 49 | +- BFS has a time and space complexity of O(m\*n) |
| 50 | +- Dynamic Programming has a time complexity of O(m\*n) and a space complexity of O(1) |
| 51 | + |
| 52 | +```javascript |
| 53 | +// Breadth-First Search |
| 54 | +const updateMatrix = function (mat) { |
| 55 | + const height = mat.length; |
| 56 | + const width = mat[0].length; |
| 57 | + |
| 58 | + const queue = []; |
| 59 | + // Finding all the zeros in the matrix and adding to the queue, mark all other cells -1 to know they are unprocessed |
| 60 | + for (let i = 0; i < height; i++) { |
| 61 | + for (let j = 0; j < width; j++) { |
| 62 | + if (mat[i][j] === 0) { |
| 63 | + queue.push([i, j]); |
| 64 | + } else { |
| 65 | + mat[i][j] = -1; |
| 66 | + } |
| 67 | + } |
| 68 | + } |
| 69 | + // directions for checking around a cell |
| 70 | + const rowDir = [0, 1, 0, -1]; |
| 71 | + const colDir = [1, 0, -1, 0]; |
| 72 | + while (queue.length > 0) { |
| 73 | + const [row, column] = queue.shift(); |
| 74 | + |
| 75 | + // Make sure cell is in bounds and hasn't been processed |
| 76 | + for (let k = 0; k < 4; k++) { |
| 77 | + const rowNext = row + rowDir[k]; |
| 78 | + const colNext = column + colDir[k]; |
| 79 | + if ( |
| 80 | + rowNext < 0 || |
| 81 | + rowNext > height - 1 || |
| 82 | + colNext < 0 || |
| 83 | + colNext > width - 1 || |
| 84 | + mat[rowNext][colNext] !== -1 |
| 85 | + ) { |
| 86 | + continue; |
| 87 | + } |
| 88 | + |
| 89 | + // Set current cell one larger than parent and then add to queue to processes it's children |
| 90 | + mat[rowNext][colNext] = mat[row][column] + 1; |
| 91 | + queue.push([rowNext, colNext]); |
| 92 | + } |
| 93 | + } |
| 94 | + return mat; |
| 95 | +}; |
| 96 | + |
| 97 | +// Dynamic Programming |
| 98 | +const updateMatrix = function (mat) { |
| 99 | + const ht = mat.length; |
| 100 | + const wd = mat[0].length; |
| 101 | + |
| 102 | + // Moving from top left to bottom right and updating cells to the minimum + 1 of the cells that are to the top left of them |
| 103 | + for (let i = 0; i < ht; i++) { |
| 104 | + for (let j = 0; j < wd; j++) { |
| 105 | + if (mat[i][j] > 0) { |
| 106 | + const top = i > 0 ? mat[i - 1][j] : Infinity; |
| 107 | + const left = j > 0 ? mat[i][j - 1] : Infinity; |
| 108 | + mat[i][j] = Math.min(top, left) + 1; |
| 109 | + } |
| 110 | + } |
| 111 | + } |
| 112 | + // Moving from bottom right to top left and updating cells to the minimum + 1 of the cells that are to the bottom right of them |
| 113 | + for (let i = ht - 1; i >= 0; i--) { |
| 114 | + for (let j = wd - 1; j >= 0; j--) { |
| 115 | + if (mat[i][j] > 0) { |
| 116 | + const btm = i < ht - 1 ? mat[i + 1][j] : Infinity; |
| 117 | + const right = j < wd - 1 ? mat[i][j + 1] : Infinity; |
| 118 | + mat[i][j] = Math.min(btm + 1, right + 1, mat[i][j]); |
| 119 | + } |
| 120 | + } |
| 121 | + } |
| 122 | + |
| 123 | + return mat; |
| 124 | +}; |
| 125 | +``` |
0 commit comments