zoukankan      html  css  js  c++  java
  • 剑指Offer_#29_顺时针打印矩阵

    剑指Offer_#29_顺时针打印矩阵

    Contents

    题目

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

    示例 1:

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

    示例 2:

    输入: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]
    

    限制:

    0 <= matrix.length <= 100
    0 <= matrix[i].length <= 100

    思路分析

    按照书中的思路,打印的过程是逐层打印的,从外到内,每一圈都顺时针的打印。
    将整个过程分为两层循环,

    • 外层循环:逐渐缩小边界,从最外圈到最内圈。
      • 每一圈遍历的起始点是(start,start),每轮循环,start增加1,即边界向内缩小一圈。
      • 循环条件start * 2 < row && start * 2 <column,可以这样理解:start必然在整个矩阵的左半部分和上半部分,超出整个范围,说明每一圈都遍历完成了,循环可以终止。
    • 内层循环:顺时针打印某一圈的元素。
      • 顺序:模拟顺时针旋转顺序,分别遍历上边界,右边界,下边界,左边界。
        顺序
      • 前提条件:除了上边界之外,其他的边界是否打印是有前提的。
        • 从上到下遍历右边界,条件:至少有两行
        • 从右到左遍历下边界,条件:至少有两行两列
        • 从下到上遍历左边界,条件:至少有三行两列
      • 循环边界条件
        • 每一圈当中的四个角落位置需要注意,不要重复访问。

    解答

    class Solution {
        int row;
        int column;
        int[] res;
        int x = 0;//res的索引
        public int[] spiralOrder(int[][] matrix) {
            //ERROR:空数组和null不是一个东西
            if(matrix == null || matrix.length == 0) return new int[0];
            //打印每一圈的开始位置(0,0),(1,1)...表示为(start,start)
            int start = 0;
            //ERROR:注意行列的长度不要搞反
            row = matrix.length;
            column = matrix[0].length;
            res = new int[row * column];
            //循环条件:开始点(start,start)应该位于矩阵的左半部分和上半部分
            //即start应小于行数和列数的一半,可以枚举简单的情况,得到这个规律
            //ERROR:不可以写成除法的形式,因为除法会出现向下取整的情况,导致误判
            //while(start < (row / 2) && start < (column / 2)){
            while(row > 2*start && column > 2*start){
                //每次从(start,start)位置开始,顺时针打印一圈
                PrintMatrixInCircle(matrix,start);
                //start++即打印范围向内缩小一圈
                start++;
            }
            return res;
        }
    
        public void PrintMatrixInCircle(int[][] matrix, int start){
            //右边界
            int endX = column - 1 - start;
            //下边界
            int endY = row - 1 - start;
            //从左到右遍历上边界
            for(int i = start;i <= endX;i++){
                res[x++] = matrix[start][i];
            }
            //从上到下遍历右边界
            //条件:至少有两行
            if(endY > start){
                //边界要排除第一个(因为在上边界里访问过了),即i是从start+1开始而非start
                for(int i = start + 1;i <= endY;i++){
                    res[x++] = matrix[i][endX];
                }
            }
            //从右到左遍历下边界
            //条件:至少有两行两列
            if(start < endX && start < endY){
                //同理,要排除第一个
                for(int i = endX - 1;i >= start;i--){
                    res[x++] = matrix[endY][i];
                }
            }
            //从下到上遍历左边界
            //条件:至少有三行两列
            if(endY - start > 1 && start < endX){
                //同理,排除第一个
                for(int i = endY - 1;i >= start + 1;--i){
                    res[x++] = matrix[i][start];
                }
            }
        }
    }
  • 相关阅读:
    获取指定目录下的所有文件
    char码值对应列表大全
    烂记性不如好笔头㈠㈢㈥
    SQL Server中的Image数据类型的操作
    企业信息化与标准化的纠结(二)
    企业信息化的前世今生
    企业信息化与标准化的纠结(一)
    关于 EOM(Enterprise Operating Model)企业经营模型(1) 转自n216
    《优秀程序员应该具备哪些素质》(ZT)
    谈谈MIS建设与职能架构的问题
  • 原文地址:https://www.cnblogs.com/Howfars/p/13237140.html
Copyright © 2011-2022 走看看