2020-09-03:裸写算法:回形矩阵遍历。
福哥答案2020-09-03:
方法一:模拟,位图方式。
跟 方法二 一样,区别是辅助矩阵visited用位图节约空间。
方法二:模拟。
可以模拟螺旋矩阵的路径。初始位置是矩阵的左上角,初始方向是向右,当路径超出界限或者进入之前访问过的位置时,则顺时针旋转,进入下一个方向。
判断路径是否进入之前访问过的位置需要使用一个与输入矩阵大小相同的辅助矩阵visited,其中的每个元素表示该位置是否被访问过。当一个元素被访问时,将 visited 中的对应位置的元素设为已访问。
如何判断路径是否结束?由于矩阵中的每个元素都被访问一次,因此路径的长度即为矩阵中的元素数量,当路径的长度达到矩阵中的元素数量时即为完整路径,将该路径返回。
复杂度分析
时间复杂度:O(mn),其中 m 和 n 分别是输入矩阵的行数和列数。矩阵中的每个元素都要被访问一次。
空间复杂度:O(mn)。需要创建一个大小为 m×n 的矩阵 visited 记录每个位置是否被访问过。
方法三:按层模拟
可以将矩阵看成若干层,首先输出最外层的元素,其次输出次外层的元素,直到输出最内层的元素。
定义矩阵的第 k 层是到最近边界距离为 k 的所有顶点。例如,下图矩阵最外层元素都是第 1 层,次外层元素都是第 2 层,剩下的元素都是第 3 层。
复杂度分析
时间复杂度:O(mn),其中 m 和 n 分别是输入矩阵的行数和列数。矩阵中的每个元素都要被访问一次。
空间复杂度:O(1)。除了输出数组以外,空间复杂度是常数。
代码用golang编写,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | package test37_spiralorder import ( "fmt" "testing" ) //https://leetcode-cn.com/problems/spiral-matrix/solution/luo-xuan-ju-zhen-by-leetcode-solution/ //go test -v -test.run TestSpiralOrder func TestSpiralOrder(t *testing.T) { const N = 3 matrix := make([][]int, N) for i := 0; i < N; i++ { matrix[i] = make([]int, N) for j := 0; j < N; j++ { matrix[i][j] = i*N + j + 1 } } fmt.Println(matrix) ret := spiralOrder1(matrix) fmt.Println(ret, "方法一:模拟,位图" ) ret = spiralOrder2(matrix) fmt.Println(ret, "方法二:模拟" ) ret = spiralOrder3(matrix) fmt.Println(ret, "方法三:按层模拟" ) } //方法一:模拟,位图 func spiralOrder1(matrix [][]int) []int { if len(matrix) == 0 || len(matrix[0]) == 0 { return []int{} } rows, columns := len(matrix), len(matrix[0]) visited := make([]byte, (rows*columns+7)/8) var ( total = rows * columns order = make([]int, total) row, column = 0, 0 directions = [][]int{[]int{0, 1}, []int{1, 0}, []int{0, -1}, []int{-1, 0}} directionIndex = 0 ) for i := 0; i < total; i++ { order[i] = matrix[row][column] SetBitMapValue(visited, row*columns+column, true) nextRow, nextColumn := row+directions[directionIndex][0], column+directions[directionIndex][1] if nextRow < 0 || nextRow >= rows || nextColumn < 0 || nextColumn >= columns || GetBitMapValue(visited, nextRow*columns+nextColumn) { directionIndex = (directionIndex + 1) % 4 } row += directions[directionIndex][0] column += directions[directionIndex][1] } return order } //方法二:模拟 func spiralOrder2(matrix [][]int) []int { if len(matrix) == 0 || len(matrix[0]) == 0 { return []int{} } rows, columns := len(matrix), len(matrix[0]) visited := make([][]bool, rows) for i := 0; i < rows; i++ { visited[i] = make([]bool, columns) } var ( total = rows * columns order = make([]int, total) row, column = 0, 0 directions = [][]int{[]int{0, 1}, []int{1, 0}, []int{0, -1}, []int{-1, 0}} directionIndex = 0 ) for i := 0; i < total; i++ { order[i] = matrix[row][column] visited[row][column] = true nextRow, nextColumn := row+directions[directionIndex][0], column+directions[directionIndex][1] if nextRow < 0 || nextRow >= rows || nextColumn < 0 || nextColumn >= columns || visited[nextRow][nextColumn] { directionIndex = (directionIndex + 1) % 4 } row += directions[directionIndex][0] column += directions[directionIndex][1] } return order } //方法三:按层模拟 func spiralOrder3(matrix [][]int) []int { if len(matrix) == 0 || len(matrix[0]) == 0 { return []int{} } var ( rows, columns = len(matrix), len(matrix[0]) order = make([]int, rows*columns) index = 0 left, right, top, bottom = 0, columns - 1, 0, rows - 1 ) for left <= right && top <= bottom { for column := left; column <= right; column++ { order[index] = matrix[top][column] index++ } for row := top + 1; row <= bottom; row++ { order[index] = matrix[row][right] index++ } if left < right && top < bottom { for column := right - 1; column > left; column-- { order[index] = matrix[bottom][column] index++ } for row := bottom; row > top; row-- { order[index] = matrix[row][left] index++ } } left++ right-- top++ bottom-- } return order } //获取位图第index元素的值 func GetBitMapValue(data []byte, index int) bool { return data[index/8]&(1<<(index%8)) != 0 } //设置位图第index元素的值 func SetBitMapValue(data []byte, index int, v bool) { if v { data[index/8] |= 1 << (index % 8) } else { data[index/8] &= ^(1 << (index % 8)) } } |
敲 go test -v -test.run TestSpiralOrder 命令,结果如下:
***
[评论](https://user.qzone.qq.com/3182319461/blog/1599087959)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具