Skip to content

Commit

Permalink
add leetcode 54
Browse files Browse the repository at this point in the history
  • Loading branch information
xxxVitoxxx committed Oct 19, 2024
1 parent ad51ca3 commit 7fc184d
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 1 deletion.
124 changes: 124 additions & 0 deletions 54.spiral_matrix/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package main

import "math"

// brute force will result in a time limit exceeded error
func spiralOrder(matrix [][]int) []int {
mixRow, mixCol := len(matrix), len(matrix[0])
result := make([]int, mixRow*mixCol)
row, col := 0, 0
result[0] = matrix[row][col]
visit := 101
matrix[row][col] = visit
direction := [][]int{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}
for i := 1; i < len(result); {
for j := 0; j < len(direction); {
newRow, newCol := row+direction[j][0], col+direction[j][1]
if newRow == mixRow || newCol == mixCol ||
newRow < 0 || newCol < 0 {
j++
continue
}

if matrix[newRow][newCol] == visit {
j++
continue
}

row, col = newRow, newCol
result[i] = matrix[row][col]
matrix[row][col] = visit
i++
if i == len(result) {
break
}
}
}

return result
}

// optimize spiralOrder
// time complexity: O(M * N) this is because we visit each element once.
// space complexity: O(1)
//
// if we mark the cells that we visited, then when we run into a visited cell,
// we know we need to run.
//
// if `changeDirection` is larger than 1, it means we are continuously
// changing our directions, and therefore we've visited all of the elements.
//
// modifying the original data may not be a good choice sometimes. therefore,
// we can also prepare another boolean matrix to store the cells we visited.
// however, the implementation of this approach is quite similar.
func spiralOrder2(matrix [][]int) []int {
m, n := len(matrix), len(matrix[0])
row, col := 0, 0
result := make([]int, 0, m*n)
visit := 101
result = append(result, matrix[row][col])
matrix[row][col] = visit

directions := [4][2]int{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}
currentDirection := 0
changeDirection := 0

for changeDirection < 2 {
for row+directions[currentDirection][0] >= 0 &&
row+directions[currentDirection][0] < m &&
col+directions[currentDirection][1] >= 0 &&
col+directions[currentDirection][1] < n &&
matrix[row+directions[currentDirection][0]][col+directions[currentDirection][1]] != visit {
row += directions[currentDirection][0]
col += directions[currentDirection][1]
result = append(result, matrix[row][col])
matrix[row][col] = visit

// reset this to 0 since we did not break and change the direction
changeDirection = 0
}
// change our direction
currentDirection = (currentDirection + 1) % 4
// increment changeDirection because we changed our direction
changeDirection++
}

return result
}

// set up boundaries
// time complexity: O(M * N)
// space complexity: O(1)

// there are only two movement pattern, right + down and left + up.
// in the first case we increment either the row or column by 1, and
// in the latter case we increment either the row or column by -1.
// also notice that after we move horizontally the number of possible
// vertical steps decrease by 1, and after we move vertically the number
// of possible horizontal steps decrease by 1. when we run out of either
// vertical steps or horizontal steps we reach the end.
func spiralOrder3(matrix [][]int) []int {
m, n := len(matrix), len(matrix[0])
direction := 1
row, col := 0, -1
result := []int{}
for math.Min(float64(m), float64(n)) != 0 {
// move horizontally
for i := 0; i < n; i++ {
col += direction
result = append(result, matrix[row][col])
}
m -= 1

// move vertically
for i := 0; i < m; i++ {
row += direction
result = append(result, matrix[row][col])
}
n -= 1

// flip direction
direction *= -1
}
return result
}
64 changes: 64 additions & 0 deletions 54.spiral_matrix/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package main

import (
"testing"
)

func TestSpiralOrder(t *testing.T) {
for _, tt := range []struct {
matrix [][]int
want []int
}{{
matrix: [][]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}},
want: []int{1, 2, 3, 6, 9, 8, 7, 4, 5},
}, {
matrix: [][]int{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}},
want: []int{1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7},
}, {
matrix: [][]int{{8, 9, 4, 1, 2, 5}, {10, 19, 32, 14, 3, 6}},
want: []int{8, 9, 4, 1, 2, 5, 6, 3, 14, 32, 19, 10},
}, {
matrix: [][]int{{-10, 0, -7}, {0, 9, -100}},
want: []int{-10, 0, -7, -100, 9, 0},
}} {
matrix1 := shallowCopy2DSlice(tt.matrix)
got := spiralOrder(matrix1)
if !equal(tt.want, got) {
t.Errorf("got: %v, want: %v", got, tt.want)
}

matrix2 := shallowCopy2DSlice(tt.matrix)
got = spiralOrder2(matrix2)
if !equal(tt.want, got) {
t.Errorf("got: %v, want: %v", got, tt.want)
}

matrix3 := shallowCopy2DSlice(tt.matrix)
got = spiralOrder3(matrix3)
if !equal(tt.want, got) {
t.Errorf("got: %v, want: %v", got, tt.want)
}
}
}

func shallowCopy2DSlice(matrix [][]int) [][]int {
shallow := make([][]int, len(matrix))
for i := range matrix {
arr := make([]int, len(matrix[i]))
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
}
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
|35|[Search Insert Position](https://leetcode.com/problems/search-insert-position)|$\color{green}{\textsf{Easy}}$|[Go]()|
|46|[Permutations](https://leetcode.com/problems/permutations/)|$\color{orange}{\textsf{Medium}}$|[Go](https://github.com/xxxVitoxxx/leetcode/blob/main/46.permutations/main.go)|
|52|[N-Queens II](https://leetcode.com/problems/n-queens-ii/)|$\color{red}{\textsf{Hard}}$|[Go](https://github.com/xxxVitoxxx/leetcode/blob/main/52.N-queens_II/main.go)|
|53|[Maximum Subarray](https://leetcode.com/problems/maximum-subarray)|$\color{orange}{\textsf{Medium}}$||
|53|[Maximum Subarray](https://leetcode.com/problems/maximum-subarray)|$\color{orange}{\textsf{Medium}}$||
|54|[Spiral Matrix](https://leetcode.com/problems/spiral-matrix/submissions)|$\color{orange}{\textsf{Medium}}$|[Go](https://github.com/xxxVitoxxx/leetcode/blob/main/54.spiral_matrix/main.go)|
|58|[Length of Last Word](https://leetcode.com/problems/length-of-last-word)|$\color{green}{\textsf{Easy}}$||
|61|[Rotate List](https://leetcode.com/problems/rotate-list)|$\color{orange}{\textsf{Medium}}$|[Go](https://github.com/xxxVitoxxx/leetcode/blob/main/61.rotate_list/main.go)|
|66|[Plus One](https://leetcode.com/problems/plus-one)|$\color{green}{\textsf{Easy}}$||
Expand Down

0 comments on commit 7fc184d

Please sign in to comment.