LeetCode59.螺旋矩阵II
https://leetcode.cn/problems/spiral-matrix-ii/
学习内容
螺旋矩阵题,就是给你一个矩阵的长度n,去返回一个螺旋表示的二维数组。 如n=3时,返回的二维数组为:
123
894
765
解题的关键点,是考虑边界上的点怎么处理,通过遍历圈数+遍历每个边来输出二维数组。
- 当每次转圈时,要考虑边界上的这个点要怎么处理。是当前遍历的这条边来处理,还是留给下条边来处理;
- 每处理一条边,对节点的处理规则不同,要去找到循环不变量,对每条边采用相同的处理规则:左闭右开 or 左闭右闭,坚持使用同一规则去处理每一条边。(左闭右开-遍历每条边时,只处理第一个节点,最后一个节点不处理,交给下一次遍历时处理)
- 开始时先给出圈数,n是边长,每转一圈边长会减2,减了几次2,就走几圈。因此圈数是n/2:
while (n/2)
- 因为遍历每一条边时,起始位置都会变,因此在进行遍历时,也要定义好起始位置。定义要填充的结果值count
startX=0
startY=0
count=1
- 除了起始位置,因为每次遍历一圈后,需要向内绕圈,元素会更少,循环次数也会改变。因此需要在遍历前再定义一个变量用来记录循环终止次数。
offset=1
- 左闭右开遍历第一条横边。定义好这几个变量后,开始遍历。在二维数组中的表示不同于(x,y)的坐标轴,往右边走是y值变动,因此从startY起始,到n-offset终止。因为我们规定是左闭右开,右边值不取,所以符号是小于。
for j=startY;j<n-offset;j++{
nums[startX][j]=count++
}
- 左闭右开遍历第二条竖边。竖边对应二维数组中改变的是x的值。左闭右开处理开始的初始值,初始值从startX开始,终值仍然是n-offset。遍历竖边的过程中,y的值是固定的。
for i=startX;i<n-offset;i++{
nums[i][j]=count++
}
- 左闭右开遍历第三条横边。这个过程中,j已经走到圈的末尾了,所以无须初始化,同样是第0位交给下一次处理。
for j>startY;j--{
nums[i][j]=count++
}
- 左闭右开遍历第四条竖边。和上个过程一致,无需初始化。
for i>startX;i--{
nums[i][j]=count++
}
- 循环条件改变。起始位置变化,以及缩小了一圈,终止位置也会变化
startX ++
startY ++
offset --
- 奇数处理。当n是奇数时,把最后一个值做填充即可。
if n % 2==0{
nums[startX][startY]=count++
}
代码
func generateMatrix(n int) [][]int {
startX:=0
startY:=0
count:=0
offset:=1
// Go语言不支持动态大小的数组。应该使用make函数创建切片来代替
// var nums [n][n]int
nums := make([][]int, n) // 二维切片,3行
for i := range nums {
nums[i] = make([]int, n) // 每一行4列
}
cycle:=n/2
for cycle > 0{
i := startX
j:=startY
for j<n-offset{
count++
nums[startX][j]=count
j++
}
for i<n-offset{
count++
nums[i][j]=count
i++
}
for i < n-offset{
count++
nums[i][j] = count
i++
}
for j>startY{
count++
nums[i][j]=count
j--
}
for i>startX{
count++
nums[i][j]=count
i--
}
cycle --
startX ++
startY ++
offset ++
}
if n % 2!=0{
count++
nums[startX][startY]=count
}
return nums
}
go补充
- 需要动态创建数组,不能直接使用静态数组创建:
var nums [n][n]int
; - 二维数组的动态创建,需要先创建行,再创建列。动态数组的含义是值可以改变,后续可以填充值。
nums := make([][]int, n) // 二维切片,3行
for i := range nums {
nums[i] = make([]int, n) // 每一行4列
}
- for循环中初始化的值:=是临时变量,后面的for不能再次使用。需要在初始值时进行定义。然后用for循环的while形式解决。
参考:
Golang二维切片初始化 https://studygolang.com/articles/34434
标准代码的改进
- 初始化定义非0变量时,用var来定义,可以确定类型;
var loop int = n/2
var center int = n/2
- for循环的遍历条件,初始给个定义,第一位用=而不用:=,改变的是该范围内的变量。
i, j := startx, starty
for j = starty; j < n-offset; j++ {
res[startx][j] = count
count++
}
- for的while写法也可以填三部分值,设置为空即可:
for ; i > startx; i-- {
res[i][j] = count
count++
}
func generateMatrix(n int) [][]int {
startx, starty := 0, 0
var loop int = n / 2
var center int = n / 2
count := 1
offset := 1
res := make([][]int, n)
for i := 0; i < n; i++ {
res[i] = make([]int, n)
}
for loop > 0 {
i, j := startx, starty
//行数不变 列数在变
for j = starty; j < n-offset; j++ {
res[startx][j] = count
count++
}
//列数不变是j 行数变
for i = startx; i < n-offset; i++ {
res[i][j] = count
count++
}
//行数不变 i 列数变 j--
for ; j > starty; j-- {
res[i][j] = count
count++
}
//列不变 行变
for ; i > startx; i-- {
res[i][j] = count
count++
}
startx++
starty++
offset++
loop--
}
if n%2 == 1 {
res[center][center] = n * n
}
return res
}
标签:count,遍历,nums,++,矩阵,LeetCode59,II,int,--
From: https://blog.51cto.com/u_15955938/7439314