題干
輸入一個矩陣牙咏,按照從外向里以順時針的順序依次打印出每一個數(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
解題思路
分析題干我們知道需要對矩陣從外向里順時針輸出,我們可以轉(zhuǎn)換成通俗的說法哈踱,就是一圈一圈的打印送悔,所以我們只需要解決兩個問題即可慢显,第一個就是在什么條件下終止打印,第二個是如何打印一圈欠啤。
對于第一個問題荚藻,我們可以分析一下,假設(shè)左上角的坐標(biāo)為(0, 0)
洁段,第二圈的起點(diǎn)就是(1, 1)
应狱,依次類推,第n圈的起點(diǎn)就是 (n-1, n-1)
祠丝,又由于我們每循環(huán)一圈疾呻,都可能會輸出兩行兩列的數(shù)據(jù),所以我們現(xiàn)在來考慮下最后一圈起點(diǎn)坐標(biāo)和行數(shù)写半、列數(shù)之間的關(guān)系岸蜗,例如:如果是 8X8
的矩陣,則最后一圈的坐標(biāo)是(3, 3)
叠蝇,行數(shù)大于兩倍的行坐標(biāo)璃岳,即8>3*2
,如果是 9X9
的矩陣悔捶,則最后一圈的坐標(biāo)是 (4, 4)
铃慷,行數(shù)大于兩倍的行坐標(biāo),即9>4*2
炎功,列數(shù)同理枚冗,由此我們可以分析得出缓溅,只要行數(shù)和列數(shù)都大于最后一圈的起點(diǎn)坐標(biāo)的行和列蛇损,則還需要循環(huán)一圈。
對于第二個問題,我們需要考慮一些特殊情況了淤齐,對于行列相同的矩陣股囊,每一圈循環(huán)都會按照從左到右,從上到下更啄,從右到左稚疹,從下到上的四個步驟完成打印,而對于一些不規(guī)則的矩陣祭务,如行數(shù)小于列數(shù)内狗,行數(shù)大于列數(shù)時,需要特別分析一下义锥,有可能出現(xiàn)缺少后面幾步的情況柳沙。
- 如果需要執(zhí)行從上到下的打印,需要循環(huán)的結(jié)束行號大于開始行號
- 如果需要執(zhí)行從右到左的打印拌倍,需要循環(huán)的結(jié)束行號大于開始行號赂鲤,且結(jié)束列號大于開始列號
- 如果需要執(zhí)行從下到上的打印,不僅僅需要循環(huán)的結(jié)束號大于開始行號柱恤,而需要結(jié)束行號-開始行號>=2数初,且結(jié)束列號大于開始列號
到此,上面的兩個問題就分析完了梗顺,可以代碼實現(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);