数组 - 螺旋矩阵2
本题以力扣上的59号题目为例。
这道题,卡哥说没有涉及什么算法,重点就是要把握好边界。我们尽量要将边界设计成统一的,不然的话每条边都一个规则容易把自己绕进去。
接下来就讲讲边界的规则:左闭右开。
这里说的边界规则是,每次循环我们如何填充数据 - 每条边上的数据我们只填起始位置到终止位置的前一个元素。比如上图:上面这条边有[1,2,3,4]四个数,我们只填充[1,2,3]这三个数,[4]我们作为右面这条边的起始位置。这样我们就统一了填充规则。
上图每个数我都编好了下标,接下来我们就对着编号进行填充数据即可,注意是从上右下左的顺序。
还有一个比较重要的点就是:我们如何控制旋转的圈数。比如给一个4,我们如何控制旋转几圈?如果不知道,我们就举例子
| 数字 | 圈数 |
|---|---|
| 1 | 1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 2 |
| 5 | 3 |
上面我是根据自己画图距离得出的结果,不过还是得注意,当n是奇数的时候如何填充数据。根据卡哥的讲解,如果是奇数,我们在循环外面填充。
以3为例,我们循环就只转一圈,中间的9我们在循环外填充
具体代码如下
// 1 2 3 4
// 12 13 14 5
// 11 16 15 6
// 10 9 8 7
func generateMatrix(n int) [][]int {
// 初始化结果对象
res := make([][]int, n)
for t := 0; t < n; t++{
res[t] = make([]int, n)
}
x, y := 0, 0 // 起始坐标位置
offset := 1 // 偏移量,因为圈是不断缩小的,每次都需要缩小1
num := 1
for p := 0; p <= n / 2 ; p++{
// 完成上部那条边
i, j := x, y // i, j就是需要变动的指针
for ; j < n - offset; j++ {
res[x][j] = num
num++
}
// 完成右部那条边
for ; i < n - offset; i++{
res[i][j] = num
num++
}
// 完成下部那条边
for ; j > x; j--{
res[i][j] = num
num++
}
// 完成左部那条边
for ; i > y; i--{
res[i][y] = num
num++
}
x++
y++
offset++
// if p % 2 == 1 {
// res[i][j] = num
// }
}
// 手动填充中间的数据
if n % 2 == 1 {
res[n/2][n/2] = n*n
}
fmt.Println(res)
return res
}
上述是力扣中的题目,下面给一个今年多抓鱼我遇到的一个算法题,和这个类似。原题大概描述一下
大家看这个图应该能知道,给定一个n,拼凑成一个等腰直角三角形,且左上角是直角。具体的思路和卡哥讲得差不多
func generateSanJiao(n int) [][]int {
// 初始化结果
res := make([][]int, n)
for t := 0; t < n; t++ {
res[t] = make([]int, n-t)
}
x, y := 0, 0
num := 1
offset := 1
for p := 0; p < n/2; p++ {
i, j := x, y
// 左
for ; i < n-offset-p; i++ {
res[i][y] = num
num++
}
// 侧
for ; i >= offset && j < n-offset-p; i, j = i-1, j+1 {
res[i][j] = num
num++
}
// 上
for ; j >= offset; j-- {
res[x][j] = num
num++
}
if n%2 == 0 {
res[i][j] = num
}
x++
y++
offset++
}
fmt.Println(res)
return res
}