美文网首页剑指Offer-PHP实现
《剑指Offer》-29.顺时针打印矩阵

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

作者: 懒人成长 | 来源:发表于2018-08-17 07:21 被阅读0次

    题干

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

     1   2   3   4
     5   6   7   8
     9  10  11  12
    13  14  15  16
    

    则依次打印出数字 1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10

    解题思路

    分析题干我们知道需要对矩阵从外向里顺时针输出,我们可以转换成通俗的说法,就是一圈一圈的打印,所以我们只需要解决两个问题即可,第一个就是在什么条件下终止打印,第二个是如何打印一圈。

    对于第一个问题,我们可以分析一下,假设左上角的坐标为(0, 0),第二圈的起点就是(1, 1),依次类推,第n圈的起点就是 (n-1, n-1),又由于我们每循环一圈,都可能会输出两行两列的数据,所以我们现在来考虑下最后一圈起点坐标和行数、列数之间的关系,例如:如果是 8X8 的矩阵,则最后一圈的坐标是(3, 3),行数大于两倍的行坐标,即8>3*2,如果是 9X9 的矩阵,则最后一圈的坐标是 (4, 4),行数大于两倍的行坐标,即9>4*2,列数同理,由此我们可以分析得出,只要行数和列数都大于最后一圈的起点坐标的行和列,则还需要循环一圈。

    对于第二个问题,我们需要考虑一些特殊情况了,对于行列相同的矩阵,每一圈循环都会按照从左到右,从上到下,从右到左,从下到上的四个步骤完成打印,而对于一些不规则的矩阵,如行数小于列数,行数大于列数时,需要特别分析一下,有可能出现缺少后面几步的情况。

    • 如果需要执行从上到下的打印,需要循环的结束行号大于开始行号
    • 如果需要执行从右到左的打印,需要循环的结束行号大于开始行号,且结束列号大于开始列号
    • 如果需要执行从下到上的打印,不仅仅需要循环的结束号大于开始行号,而需要结束行号-开始行号>=2,且结束列号大于开始列号

    到此,上面的两个问题就分析完了,可以代码实现了。

    代码实现

    <?php
    /**
     * @param array $arr 二维数组
     * @param int $columns 列数
     * @param int $rows 行数
     */
    function printMatrixClockwisely(array $arr, int $columns, int $rows)
    {
        if ($arr == null || $columns == 0 || $rows == 0) {
            return;
        }
        $start = 0;
        while ($columns > $start * 2 && $rows > $start * 2) {
            printMatrixInCircle($arr, $columns, $rows, $start);
            $start++;
        }
    }
    
    /**
     * @param array $arr 二维数组
     * @param int $columns 列数
     * @param int $rows 行数
     * @param int $start 圈号
     */
    function printMatrixInCircle(array $arr, int $columns, int $rows, int $start)
    {
        // 从0开始,需要额外减1
        $endRow = $rows - $start - 1;
        $endColumn = $columns - $start - 1;
    
        // 从左至右输出
        for ($i = $start; $i <= $endColumn; $i++) {
            $num = $arr[$start][$i];
            printNum($num);
        }
    
        // 从上至下输出
        if ($endRow > $start) {
            for ($i = $start + 1; $i <= $endRow; $i++) {
                $num = $arr[$i][$endColumn];
                printNum($num);
            }
        }
        // 从右至左输出
        if ($endRow > $start && $endColumn > $start) {
            for ($i = $endColumn - 1; $i >= $start; $i--) {
                $num = $arr[$endRow][$i];
                printNum($num);
            }
        }
    
        // 从下至上输出
        if ($endColumn > $start && $endRow - $start > 1) {
            for ($i = $endRow - 1; $i > $start; $i--) {
                $num = $arr[$i][$start];
                printNum($num);
            }
        }
    }
    
    function printNum($num)
    {
        printf('%3d', $num);
    }
    
    
    $arr = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]];
    printMatrixClockwisely($arr, 4, 4);
    

    相关文章

      网友评论

        本文标题:《剑指Offer》-29.顺时针打印矩阵

        本文链接:https://www.haomeiwen.com/subject/rmaabftx.html