diff --git a/73.set_matrix_zeroes/main.go b/73.set_matrix_zeroes/main.go new file mode 100644 index 0000000..348c366 --- /dev/null +++ b/73.set_matrix_zeroes/main.go @@ -0,0 +1,118 @@ +package main + +// additional memory approach +// time complexity: O(M * N) where M and N are the number +// of the rows and columns +// +// space complexity: O(M + N) +func setZeroes(matrix [][]int) { + rows := make(map[int]bool) + cols := make(map[int]bool) + for i := 0; i < len(matrix); i++ { + for j := 0; j < len(matrix[0]); j++ { + if matrix[i][j] == 0 { + rows[i], cols[j] = true, true + } + } + } + + for i := 0; i < len(matrix); i++ { + for j := 0; j < len(matrix[0]); j++ { + if rows[i] || cols[j] { + matrix[i][j] = 0 + } + } + } +} + +// use the matrix itself as the indicators +// time complexity: O(M * N) +// space complexity: O(1) +// +// the ideas is that we can use the first cell of every row +// and column as a flag. this flag would determine whether +// a row or column has been set to zero. +func setZeroes2(matrix [][]int) { + rows, cols := len(matrix), len(matrix[0]) + zeroRow, zeroCol := false, false + for row := 0; row < rows; row++ { + for col := 0; col < cols; col++ { + if matrix[row][col] == 0 { + if row == 0 { + zeroRow = true + } else { + matrix[row][0] = 0 + } + + if col == 0 { + zeroCol = true + } else { + matrix[0][col] = 0 + } + } + } + } + + for row := 1; row < rows; row++ { + for col := 1; col < cols; col++ { + if matrix[row][0] == 0 || matrix[0][col] == 0 { + matrix[row][col] = 0 + } + } + } + + if zeroRow { + for col := 0; col < cols; col++ { + matrix[0][col] = 0 + } + } + + if zeroCol { + for row := 0; row < rows; row++ { + matrix[row][0] = 0 + } + } +} + +// same ideas as setZeroes2 +// time complexity: O(M * N) +// space complexity: O(1) +func setZeroes3(matrix [][]int) { + rows, cols := len(matrix), len(matrix[0]) + zeroCol := false + for row := 0; row < rows; row++ { + if matrix[row][0] == 0 { + zeroCol = true + } + + for col := 1; col < cols; col++ { + // as a flag + if matrix[row][col] == 0 { + matrix[0][col] = 0 + // wether which element is zero in row[0], matrix[0][0] will be setting to zero + // so if matrix[0][0] is zero that mean all of element in the first row must be to set zero + matrix[row][0] = 0 + } + } + } + + for row := 1; row < rows; row++ { + for col := 1; col < cols; col++ { + if matrix[0][col] == 0 || matrix[row][0] == 0 { + matrix[row][col] = 0 + } + } + } + + if matrix[0][0] == 0 { + for col := 1; col < cols; col++ { + matrix[0][col] = 0 + } + } + + if zeroCol { + for row := 0; row < rows; row++ { + matrix[row][0] = 0 + } + } +} diff --git a/73.set_matrix_zeroes/main_test.go b/73.set_matrix_zeroes/main_test.go new file mode 100644 index 0000000..e764dd2 --- /dev/null +++ b/73.set_matrix_zeroes/main_test.go @@ -0,0 +1,65 @@ +package main + +import ( + "testing" +) + +func TestSetZeroes(t *testing.T) { + for _, tt := range []struct { + matrix [][]int + want [][]int + }{{ + matrix: [][]int{{1, 1, 1}, {1, 0, 1}, {1, 1, 1}}, + want: [][]int{{1, 0, 1}, {0, 0, 0}, {1, 0, 1}}, + }, { + matrix: [][]int{{0, 1, 2, 0}, {3, 4, 5, 2}, {1, 3, 1, 5}}, + want: [][]int{{0, 0, 0, 0}, {0, 4, 5, 0}, {0, 3, 1, 0}}, + }} { + matrix1 := shallowCopy2DSlice(tt.matrix) + setZeroes(matrix1) + for i := 0; i < len(matrix1); i++ { + if !equal(tt.want[i], matrix1[i]) { + t.Errorf("got: %v, want: %v", matrix1[i], tt.want[i]) + } + } + + matrix2 := shallowCopy2DSlice(tt.matrix) + setZeroes2(matrix2) + for i := 0; i < len(matrix2); i++ { + if !equal(tt.want[i], matrix2[i]) { + t.Errorf("got: %v, want: %v", matrix2[i], tt.want[i]) + } + } + + matrix3 := shallowCopy2DSlice(tt.matrix) + setZeroes3(matrix3) + for i := 0; i < len(matrix3); i++ { + if !equal(tt.want[i], matrix3[i]) { + t.Errorf("got: %v, want: %v", matrix3[i], tt.want[i]) + } + } + } +} + +func shallowCopy2DSlice(matrix [][]int) [][]int { + shallow := make([][]int, len(matrix)) + for i := range matrix { + arr := make([]int, len(matrix[0])) + copy(arr, matrix[i]) + shallow[i] = arr + } + return shallow +} + +func equal(expect, actual []int) bool { + if len(expect) != len(actual) { + return false + } + + for i := 0; i < len(expect); i++ { + if expect[i] != actual[i] { + return false + } + } + return true +} diff --git a/README.md b/README.md index 43b80e1..7d73003 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,8 @@ |66|[Plus One](https://leetcode.com/problems/plus-one)|$\color{green}{\textsf{Easy}}$|| |67|[Add Binary](https://leetcode.com/problems/add-binary)|$\color{green}{\textsf{Easy}}$|| |69|[Sqrt(x)](https://leetcode.com/problems/sqrtx)|$\color{green}{\textsf{Easy}}$|| -|70|[Climbing Stairs](https://leetcode.com/problems/climbing-stairs)|$\color{green}{\textsf{Easy}}$|| +|70|[Climbing Stairs](https://leetcode.com/problems/climbing-stairs)|$\color{green}{\textsf{Easy}}$|| +|73|[Set Matrix Zeroes](https://leetcode.com/problems/set-matrix-zeroes)|$\color{orange}{\textsf{Medium}}$|[Go](https://github.com/xxxVitoxxx/leetcode/blob/main/73.set_matrix_zeroes/main.go)| |75|[Sort Colors](https://leetcode.com/problems/sort-colors)|$\color{orange}{\textsf{Medium}}$|[Go](https://github.com/xxxVitoxxx/leetcode/blob/main/75.sort_colors/main.go)| |83|[Remove Duplicates from Sorted List](https://leetcode.com/problems/remove-duplicates-from-sorted-list)|$\color{green}{\textsf{Easy}}$|| |88|[Merge Sorted Array](https://leetcode.com/problems/merge-sorted-array)|$\color{green}{\textsf{Easy}}$|[Go](https://github.com/xxxVitoxxx/leetcode/blob/main/88.merge_sorted_array/main.go)|