《劍指Offer》-29.順時針打印矩陣

題干

輸入一個矩陣,按照從外向里以順時針的順序依次打印出每一個數(shù)字。例如,如果輸入如下矩陣:

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

則依次打印出數(shù)字 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),又由于我們每循環(huán)一圈,都可能會輸出兩行兩列的數(shù)據(jù),所以我們現(xiàn)在來考慮下最后一圈起點坐標和行數(shù)、列數(shù)之間的關系,例如:如果是 8X8 的矩陣,則最后一圈的坐標是(3, 3),行數(shù)大于兩倍的行坐標,即8>3*2,如果是 9X9 的矩陣,則最后一圈的坐標是 (4, 4),行數(shù)大于兩倍的行坐標,即9>4*2,列數(shù)同理,由此我們可以分析得出,只要行數(shù)和列數(shù)都大于最后一圈的起點坐標的行和列,則還需要循環(huán)一圈。

對于第二個問題,我們需要考慮一些特殊情況了,對于行列相同的矩陣,每一圈循環(huán)都會按照從左到右,從上到下,從右到左,從下到上的四個步驟完成打印,而對于一些不規(guī)則的矩陣,如行數(shù)小于列數(shù),行數(shù)大于列數(shù)時,需要特別分析一下,有可能出現(xiàn)缺少后面幾步的情況。

  • 如果需要執(zhí)行從上到下的打印,需要循環(huán)的結束行號大于開始行號
  • 如果需要執(zhí)行從右到左的打印,需要循環(huán)的結束行號大于開始行號,且結束列號大于開始列號
  • 如果需要執(zhí)行從下到上的打印,不僅僅需要循環(huán)的結束號大于開始行號,而需要結束行號-開始行號>=2,且結束列號大于開始列號

到此,上面的兩個問題就分析完了,可以代碼實現(xiàn)了。

代碼實現(xiàn)

<?php
/**
 * @param array $arr 二維數(shù)組
 * @param int $columns 列數(shù)
 * @param int $rows 行數(shù)
 */
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 二維數(shù)組
 * @param int $columns 列數(shù)
 * @param int $rows 行數(shù)
 * @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);
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容