顺时针打印矩阵
题目描述
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 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.
分析
在查看这道题的解题思路时,发现一个很不错的回答。
- 先将矩阵第一行的值另外存起来,然后删掉第一行。
- 矩阵逆时针旋转90°,再存第一行的值,再删掉。
- 直到矩阵为空时,停止。
这有点像小时候吃的大大卷泡泡糖,一圈一圈顺出来。
你也可以将矩阵写在纸上,拿完第一行,划掉,然后逆时针旋转90°,再划掉,直到全部划完。这样可以更直观看到矩阵的变化。
代码
<?php
namespace app\test\controller;
class Test
{
public function printMatrix()
{
$matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]
];
$newMatrix = [];
while ($matrix) { // 当矩阵不为空时
$newMatrix[] = $matrix[0]; // 取第一行
unset($matrix[0]); // 取完后删除
if (empty($matrix)) break; // 矩阵为空时跳出循环
$matrix = $this->turn($matrix); // 逆时针旋转矩阵
}
// 二维数组(矩阵)转为一维数组
$end = [];
foreach ($newMatrix as $k => $v)
foreach ($v as $i)
$end[] = $i;
// 打印结果
halt($end);
}
// 逆时针旋转矩阵
public function turn ($matrix){
$res = []; // 存储旋转后的结果
while(true) {
$temp=[];
foreach($matrix as $k => $v) {
$temp[] = array_pop($matrix[$k]); // 取每一行的最后一个
}
$res[] = $temp;
if (empty(array_filter($matrix))) break;
}
return $res;
}
}
笔记
在turn()函数
一开始是通过判断empty($matrix)
为空时跳出循环,运行后一直在加载,怀疑陷入了死循环。调试后发现,empty($matrix)
一直为false
,换成count($matrix)
,仍然为false
。查看了下$matrix
的值,发现是有3个空数组的数组。原来,array_pop($matrix[$k])
是弹出了元素,但数组仍在。如下所示,打印了下,查看结果。
$matrix = [[],[],[]];
dump(empty($matrix)); // false
dump(count($matrix)); // 3
这下明白原代码作者为啥要使用array_filter($matrix)
。array_filter()
如果没有传第二个参数(即回调函数),则默认过滤值为 false 的元素。这里过滤掉了空数组,过滤后 $matrix 结果为[]
,可正确跳出循环。