剑指Offer 29 - 顺时针打印矩阵

Posted xintangchn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指Offer 29 - 顺时针打印矩阵相关的知识,希望对你有一定的参考价值。

题目描述

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

思路一:顺时针旋转路径

从左上角出发,初始方向向右,当超出边界或进入之前访问过的区域时,顺时针旋转方向。

要点: 

  1. 判断某位置是否已访问过:用一个布尔数组记录,访问过的位置标记为1
  2. 顺时针方向旋转的实现:
    用一个二维数组directions表示前进方向:{{0,1}, {1,0}, {0,-1}, {-1, 0}}
    索引0-3表示:向右(行数不变,列数加一),向下(列数加一,行数不变),向左(行数不变,列数减一),向上(列数减一,行数不变)
    向右走一步: row += directions[0][0],col += directions[0][1], 以此类推
    顺时针旋转,即前进方向改为下一个索引,越界则循环:directionIndex = (1 + directionIndex) % 4

代码:

var spiralOrder = function(matrix) {
    if(matrix == null || matrix.length === 0) return [];
    
    const rows = matrix.length, cols= matrix[0].length;
    const total = rows * cols;
    
    let visited = new Array();
    for(let i = 0; i < rows; i++){
        visited[i] = new Array();
        for(let j = 0; j < cols; j++){
            visited[i][j] = 0;
        }
    }
    
    
    let res = [];
    
    const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]];
    let directionIndex = 0;
    
    let i = 0, j = 0;
    for(let n = 0; n < total; n++){
        res[n] = matrix[i][j];
        visited[i][j] = 1;
        let nextRow = i + directions[directionIndex][0];
        let nextCol = j + directions[directionIndex][1];
        
        if(nextRow >= rows || nextRow < 0 || nextCol >= cols || nextCol < 0 || visited[nextRow][nextCol]){
            directionIndex = (directionIndex + 1) % 4;
        }
        
        i = i + directions[directionIndex][0];
        j = j + directions[directionIndex][1];
        
    }
    
    return res;
};

 

易错点:

  1. visited数组需要初始化
  2. 数组越界注意上下界都要判断
  3. corner case:矩阵为空

思路二: 一层一层打印

用 left, right, top, buttom 标记当前打印的层数的边界,最后一行/一列单独打印。

代码:

var spiralOrder = function(matrix) {
    
    if(matrix == null || matrix.length === 0) return [];
    let rows = matrix.length, cols = matrix[0].length;
    let left = 0, right = cols - 1, top = 0, buttom = rows - 1;
    let res = [];
    
    while(left < right && top < buttom){
        //
        for(let j = left; j < right; j++){
            res.push(matrix[top][j]);
        }
        //
        for(let i = top; i < buttom; i++){
            res.push(matrix[i][right]);
        }
        //
        for(let j = right; j > left; j--){
            res.push(matrix[buttom][j]);
        }
        //
        for(let i = buttom; i > top; i--){
            res.push(matrix[i][left]);
        }
        
        left++; 
        right--;
        top++; 
        buttom--;
    }
    
    //最后一列
    if(left === right){
        for(let i = top; i <= buttom; i++){
            res.push(matrix[i][left])
        }
    }
    //最后一行
    else if(top === buttom){
        for(let j = left; j <= right; j++){
            res.push(matrix[top][j]);
        }
    }
    
    return res;
};

 

以上是关于剑指Offer 29 - 顺时针打印矩阵的主要内容,如果未能解决你的问题,请参考以下文章

剑指offer面试题 29. 顺时针打印矩阵

剑指offer面试题 29. 顺时针打印矩阵

Java 剑指offer(29) 顺时针打印矩阵

完整可运行代码剑指 Offer 29. 顺时针打印矩阵

完整可运行代码剑指 Offer 29. 顺时针打印矩阵

剑指 Offer 29. 顺时针打印矩阵