題干
輸入一個矩陣,按照從外向里以順時針的順序依次打印出每一個數(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);