给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
方法一:模拟
模拟矩阵的生成。按照要求,初始位置设为矩阵的左上角,初始方向设为向右。若下一步的位置超出矩阵边界,或者是之前访问过的位置,则顺时针旋转,进入下一个方向。如此反复直至填入 n^2
个元素。记 matrix 为生成的矩阵,其初始元素设为 0。由于填入的元素均为正数,我们可以判断当前位置的元素值,若不为 0,则说明已经访问过此位置。
前置知识点:
1.type用于类型定义(type definition)与类型别名(type alias)。
类型定义即定义新类型,是一个全新的类型,但可能与被定义类型存在一些关系,如类型转换,方法继承等。
类型别名则是对被定义类型的别称,与其是相同的类型,只不过取了另外一个名字而已。
类型定义:
type House struct {
height float32
width float32
}
type Handler func(name string)
func process(h Handler) {
h("test")
}
类型别名:
type House struct {
height float32
width float32
}
type Fangzi = House //类型别名
在语法上,类型别名与类型定义的差别仅仅是一个=号。但从上述示例可知,对Fangzi的改变,同样会体现在House上。Fangzi添加了Area方法,同时House也获得了计算Area的能力。这一点与类型定义是明显不同的。
从这里可以看出,类型别名的一个好处在于可以为不喜欢的类型取一个漂亮的名字。
代码如下:
type pair struct{x, y int}//类型定义
var dirs = []pair{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}//构造pair类型的数组,存放x、y下标,表示右下左上
func generateMatrix(n int) [][]int {
//构造矩阵
matrix := make([][]int, n)
for i := range matrix{
matrix[i] = make([]int, n)
}
//初始化为左上角,初始向右
row, col, dirIdx := 0, 0, 0
for i := 1; i <= n * n; i++{//存放元素
//至少有左上角
matrix[row][col] = i
//下一位置的方向
dir := dirs[dirIdx]
//判断下一位置是否越界
if r, c := row + dir.x, col + dir.y; r < 0 || r >= n || c < 0 || c >= n || matrix[r][c] > 0{
dirIdx = (dirIdx + 1) % 4
dir = dirs[dirIdx]
}
row += dir.x
col += dir.y
}
return matrix
}
方法二:按层模拟
可以将矩阵看成若干层,首先填入矩阵最外层的元素,其次填入矩阵次外层的元素,直到填入矩阵最内层的元素。
定义矩阵的第 k 层是到最近边界距离为 k 的所有顶点。例如,下图矩阵最外层元素都是第 1层,次外层元素都是第 2 层,最内层元素都是第 3 层。
对于每层,从左上方开始以顺时针的顺序填入所有元素。假设当前层的左上角位于(top,left),右下角位于(bottom,right),按照如下顺序填入当前层的元素。
从左到右填入上侧元素,依次为 (top,left) 到 (top,right)。
从上到下填入右侧元素,依次为(top+1,right) 到 (bottom,right)。
如果 left<right 且 top<bottom,则从右到左填入下侧元素,依次为 (bottom,right−1) 到 (bottom,left+1),以及从下到上填入左侧元素,依次为 (bottom,left) 到 (top+1,left)。
填完当前层的元素之后,将 left 和 top 分别增加 1,将 right 和bottom 分别减少 1,进入下一层继续填入元素,直到填完所有元素为止。
func generateMatrix(n int) [][]int {
//构造矩阵
matrix := make([][]int, n)
for i := range matrix{
matrix[i] = make([]int, n)
}
//初始化元素
num := 1
//初始化左上 右下
left, right, top, bottom := 0, n - 1, 0, n - 1
for left <= right && top <= bottom{//边界条件
//上 与 右
for column := left; column <= right; column++{
matrix[top][column] = num
num++
}
for row := top + 1; row <= bottom; row++{
matrix[row][right] = num
num++
}
if left < right && top < bottom{//至少还剩两行两列时
//下 左
for column := right - 1; column > left; column--{
matrix[bottom][column] = num
num++
}
for row := bottom; row > top; row--{
matrix[row][left] = num
num++
}
}
//下一个内圈
left++
right--
top++
bottom--
}
return matrix
}