数组——螺旋矩阵II

这一篇记录代码随想录,与螺旋矩阵相关的问题,以leetcode 第59.螺旋矩阵II为例。

题目:给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。

示例:

输入: 3 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]

Carl哥代码随想录中,通过按层模拟解决:

  • 填充上行,从左到右
  • 填充右列,从上到下
  • 填充下行,从右到左
  • 填充左列,从下到上

关键点就是:每次填充行或列,一定要坚持左闭右开的原则。即每一条边从头开始遍历到尾的前一个元素,不遍历尾。

如下图所示,把拐角交给新的边来处理:

之所以坚持左闭右开,是为了固定一个规则。否则,若是横的边从头遍历到尾,竖的边掐头去尾,对于每一条边的遍历规则就不一样了。并且,在下面代码实现中,用左闭右开的原则,可以感受到代码的整洁美。

int startx = 0;        // 每一圈开始遍历元素的x坐标
int starty = 0;        // 每一圈开始遍历元素的y坐标
int offset = 1;        // 初始是第1圈
int value = 1;         // 填充的数值
int loop = n / 2;      // 需要遍历loop圈。这个可以画图推一下,奇数维loop圈后只剩中间一个元素未遍历,偶数维loop圈后全部遍历完毕   
int[][] ans = new int[n][n];

while (loop-- > 0) {
    int i = startx;
    int j = starty;
    
    for ( ; j < n - offset; j++) // 上行,从左到右,左闭右开
        ans[i][j] = value++;
    for ( ; i < n - offset; i++) // 右列,从上到下,左闭右开
        ans[i][j] = value++;
    for ( ; j > starty; j--)              // 下行,从右到左,左闭右开
        ans[i][j] = value++;
    for ( ; i > startx; i--)              // 左列,从下到上,左闭右开
        ans[i][j] = value++;
    
    startx++;
    starty++;
    offset++; 
}
if (n % 2 == 1) {                // 奇数维的矩阵,中间那个元素额外填充
    ans[startx][starty] = value;
}
return ans;

 ——————————————————————————————————————————

代码随想录中,推荐的相似题目是:54.螺旋矩阵剑指Offer 29.顺时针打印矩阵

螺旋矩阵

螺旋矩阵II中的矩阵行列数相等,是一个方阵,而螺旋矩阵中的矩阵就是普遍的矩阵,行列数不定。因此,螺旋矩阵II 是螺旋矩阵的一个特殊形式。

同样,坚持左闭右开的原则。不同的是,这里的矩阵行列数可能不一致,那么,一些细节需要改变。

首先,是while循环遍历的圈数,即loop的值。显然,loop的值应该是min(row, column) / 2,即行数和列数 较小值除以2,可以画图推导一下。

其次,是当min(row, column) 是奇数时,遍历完loop圈后,会剩下中间一行 或一列没有遍历,此时需要额外遍历,就如同螺旋矩阵II 中需要额外填充中间那个元素一样。

int m = matrix.length;            // 矩阵行数
int n = matrix[0].length;         // 矩阵列数
int startx = 0;
int starty = 0;
int offset = 1;
int loop = Math.min(m, n) / 2;
List<Integer> ans = new ArrayList<>();

while (loop-- > 0) {
    int i = startx;
    int j = starty;
    
    for ( ; j < n - offset; j++)    // 上行
        ans.add(matrix[i][j]);
    for ( ; i < m - offset; i++)    // 右列
        ans.add(matrix[i][j]);
    for ( ; j > starty; j--)
        ans.add(matrix[i][j]);      // 下行
    for ( ; i > startx; i--)
        ans.add(matrix[i][j]);      // 左列
    
    startx++;
    starty++;
    offset++;
}
if (Math.min(m, n) % 2 == 1) {      // 行数和列数 较小值是奇数,需要额外遍历
    if (m < n) {
        for ( ; starty < n - offset + 1; starty++)    // 行数<列数,遍历一行
            ans.add(matrix[startx][starty]);
    } else {
        for ( ; startx < m - offset + 1; startx++)    // 行数>=列数,遍历一列
            ans.add(matrix[startx][starty]);
    }
}
return ans;

顺时针打印矩阵

这一题相较于螺旋矩阵,只需要注意题目中的边界限制即可,他允许行数或列数为0。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值