前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面了一圈,一个 offer 也没收到...

面了一圈,一个 offer 也没收到...

作者头像
五分钟学算法
发布2022-05-27 16:05:50
4370
发布2022-05-27 16:05:50
举报
文章被收录于专栏:五分钟学算法

大家好,我是吴师兄。

金三银四快要过去了,大家拿到了理想的 Offer 吗?

不管有没有,平时还是得把八股文等基础知识学习好。

今天分享的题目是剑指 Offer 29. 顺时针打印矩阵

题目描述如下:

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。

示例 1:

代码语言:javascript
复制
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]

直接来看分析。

对于一个二维矩阵来说,它包含了如下的边界与打印顺序:

  • 1、顶层,我们可以定义为 top,在顶层是按照从左到右的顺序进行打印
  • 2、右列,我们可以定义为 right,在右列是按照从上到小的顺序进行打印
  • 3、底层,我们可以定义为 bottom,在顶层是按照从右到左的顺序进行打印
  • 2、左列,我们可以定义为 left,在左列是按照从下到上的顺序进行打印

在打印的过程中,矩阵的可打印区间在不断的发生变化:

  • 每当把从左到右把一行打印完毕之后,整个矩阵就在顶部少了一层,即 top 位置向下挪了一层
  • 每当把从上到下把一列打印完毕之后,整个矩阵就在右部少了一列,即 right 位置向左挪了一列
  • 每当把从右到左把一行打印完毕之后,整个矩阵就在底部少了一层,即 bottom 位置向上挪了一层
  • 每当把从下到上把一列打印完毕之后,整个矩阵就在左部少了一列,即 left 位置向右挪了一列

每当 top、right、bottom、left 发生挪动之后,需要判断它们挪动之后的区间是否还存在。

  • 1、如果还存在,那么就继续按照 top、right、bottom、left 的顺序进行打印
  • 2、如果不存在了,那么说明矩阵中的所有元素打印完毕

顺着这个思路,五分钟写完代码:

代码语言:javascript
复制
// 登录 AlgoMooc 官网获取更多算法图解
// https://www.algomooc.com
// 作者:程序员吴师兄
// 代码有看不懂的地方一定要私聊咨询吴师兄呀
class Solution {
    public int[] spiralOrder(int[][] matrix) {
        
        // 特殊情况,边界处理,比如 matrix = [],无法获取  matrix[0]
        if (matrix.length == 0) {
            return new int[0];
        }

        // 设置一个一维数组 res 用来记录二维数组 matrix 中的顺时针打印的结果
        int[] res = new int[matrix.length * matrix[0].length];

        // 在打印的过程中,不断的缩小着打印的区间
        // 每当把从左到右把一行打印完毕之后,整个矩阵就在顶部少了一层,后续打印不需要再去处理它们
        // 每当把从上到下把一列打印完毕之后,整个矩阵就在右部少了一列,后续打印不需要再去处理它们
        // 每当把从右到左把一行打印完毕之后,整个矩阵就在底部少了一层,后续打印不需要再去处理它们
        // 每当把从下到上把一列打印完毕之后,整个矩阵就在左部少了一列,后续打印不需要再去处理它们
        // 因此,设置四个变量,用来记录打印的区间变化

        // top 表示顶部所在的层数位置,一开始在第 0 层
        int top = 0 ;

        // bottom 表示底部所在的层数位置,一开始在第 matrix.length - 1 层
        int bottom = matrix.length - 1 ;

        // left 表示左部所在的列数位置,一开始在第 0 列
        int left = 0 ; 

        // right 表示右部所在的列数位置,一开始在第 matrix[0].length - 1 列
        int right = matrix[0].length - 1;

        // 顺时针打印矩阵过程中,填充 res 数组,从索引位置 0 的地方开始填充
        int index = 0;

        // 使用一个 while 循环进行打印,只要打印区间中还有值就一直打印
        // 直到出现边界越界,即打印区间不存在元素了,跳出循环
        while (true) {

            // 1、从左到右,打印这一行
            // 此时,边界从 left 到 right
            for (int i = left; i <= right; i++) {

                // 将当前元素填充到 res 中
                // 此时,一直都是在 top 这一层
                res[index] = matrix[top][i];

                // index 的元素填充完毕之后,开始填充下一个元素
                index++;

            }

            // 经过上面这个循环之后,此时,顶部这一层的所有元素已经打印完毕
            // 整个打印区间需要删除这一行了,因此,将 top 的层数向下挪
            top += 1;

            // 如果此时发现顶部位置越过了底部位置,说明整个打印区间已经没有元素了
            // 跳出循环即可
            if ( top > bottom ) {
                break;
            }

            // 2、从上到下,打印这一列
            // 此时,边界从 top 到 bottom
            for (int i = top; i <= bottom; i++) {

                // 将当前元素填充到 res 中
                // 此时,一直都是在 right 这一列
                res[index] = matrix[i][right];

                // index 的元素填充完毕之后,开始填充下一个元素
                index++;

            }

            // 经过上面这个循环之后,此时,右部这一列的所有元素已经打印完毕
            // 整个打印区间需要删除这一列了,因此,将 right 的层数向左挪
            right -= 1;

            // 如果此时发现右部位置越过了左部位置,说明整个打印区间已经没有元素了
            // 跳出循环即可
            if ( right < left ) {
                break;
            }

            // 3、从右到左,打印这一行
            // 此时,边界从 right 到 left
            for (int i = right; i >= left; i--) {

                // 将当前元素填充到 res 中
                // 此时,一直都是在 bottom 这一层
                res[index] = matrix[bottom][i];

                // index 的元素填充完毕之后,开始填充下一个元素
                index++;

            }

            // 经过上面这个循环之后,此时,底部这一层的所有元素已经打印完毕
            // 整个打印区间需要删除这一行了,因此,将 bottom 的层数向上挪
            bottom -= 1;

            // 如果此时发现顶部位置越过了底部位置,说明整个打印区间已经没有元素了
            // 跳出循环即可
            if ( bottom < top ) {
                break;
            }

            // 4、从下到上,打印这一列
            // 此时,边界从 bottom 到 top
            for (int i = bottom; i >= top; i--) {

                // 将当前元素填充到 res 中
                // 此时,一直都是在 left 这一列
                res[index] = matrix[i][left];

                // index 的元素填充完毕之后,开始填充下一个元素
                index++;
            }

            // 经过上面这个循环之后,此时,左部这一列的所有元素已经打印完毕
            // 整个打印区间需要删除这一列了,因此,将 left 的层数向右挪
            left += 1;

            // 如果此时发现右部位置越过了左部位置,说明整个打印区间已经没有元素了
            // 跳出循环即可
            if ( left > right ) {
                break;
            }

        }

        // 最后,返回结果即可
        return res;
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 五分钟学算法 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档