一.数组(22)59. 螺旋矩阵 II

59. 螺旋矩阵 II

给你一个正整数 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
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值