0
点赞
收藏
分享

微信扫一扫

LeetCode59.螺旋矩阵II

LeetCode59.螺旋矩阵II

https://leetcode.cn/problems/spiral-matrix-ii/

学习内容

螺旋矩阵题,就是给你一个矩阵的长度n,去返回一个螺旋表示的二维数组。 如n=3时,返回的二维数组为:

123
894
765

解题的关键点,是考虑边界上的点怎么处理,通过遍历圈数+遍历每个边来输出二维数组。

  • 当每次转圈时,要考虑边界上的这个点要怎么处理。是当前遍历的这条边来处理,还是留给下条边来处理;
  • 每处理一条边,对节点的处理规则不同,要去找到循环不变量,对每条边采用相同的处理规则:左闭右开 or 左闭右闭,坚持使用同一规则去处理每一条边。(左闭右开-遍历每条边时,只处理第一个节点,最后一个节点不处理,交给下一次遍历时处理)
  1. 开始时先给出圈数,n是边长,每转一圈边长会减2,减了几次2,就走几圈。因此圈数是n/2:

while (n/2)

  1. 因为遍历每一条边时,起始位置都会变,因此在进行遍历时,也要定义好起始位置。定义要填充的结果值count

startX=0
startY=0
count=1

  1. 除了起始位置,因为每次遍历一圈后,需要向内绕圈,元素会更少,循环次数也会改变。因此需要在遍历前再定义一个变量用来记录循环终止次数。

offset=1

  1. 左闭右开遍历第一条横边。定义好这几个变量后,开始遍历。在二维数组中的表示不同于(x,y)的坐标轴,往右边走是y值变动,因此从startY起始,到n-offset终止。因为我们规定是左闭右开,右边值不取,所以符号是小于。

for j=startY;j<n-offset;j++{
  nums[startX][j]=count++
}

  1. 左闭右开遍历第二条竖边。竖边对应二维数组中改变的是x的值。左闭右开处理开始的初始值,初始值从startX开始,终值仍然是n-offset。遍历竖边的过程中,y的值是固定的。

for i=startX;i<n-offset;i++{
  nums[i][j]=count++
}

  1. 左闭右开遍历第三条横边。这个过程中,j已经走到圈的末尾了,所以无须初始化,同样是第0位交给下一次处理。

for j>startY;j--{
  nums[i][j]=count++
}

  1. 左闭右开遍历第四条竖边。和上个过程一致,无需初始化。

for i>startX;i--{
  nums[i][j]=count++
}

  1. 循环条件改变。起始位置变化,以及缩小了一圈,终止位置也会变化

startX ++
startY ++
offset --

  1. 奇数处理。当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补充

  1. 需要动态创建数组,不能直接使用静态数组创建:var nums [n][n]int
  2. 二维数组的动态创建,需要先创建行,再创建列。动态数组的含义是值可以改变,后续可以填充值。

nums := make([][]int, n) // 二维切片,3行
for i := range nums {
    nums[i] = make([]int, n) // 每一行4列
}

  1. for循环中初始化的值:=是临时变量,后面的for不能再次使用。需要在初始值时进行定义。然后用for循环的while形式解决。

参考:

Golang二维切片初始化 https://studygolang.com/articles/34434

标准代码的改进

  1. 初始化定义非0变量时,用var来定义,可以确定类型;

var loop int = n/2
var center int = n/2

  1. for循环的遍历条件,初始给个定义,第一位用=而不用:=,改变的是该范围内的变量。

i, j := startx, starty
for j = starty; j < n-offset; j++ {
  res[startx][j] = count
  count++
}

  1. 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
}

举报

相关推荐

0 条评论