题目
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出第一个数字。如图:如果输入以下矩阵:
思路
由于是以从外圈到内圈的顺序依次打印,我们可以把矩阵想象成若干个圈,每一次打印矩阵中的一个圈。
如果以最外圈开始打印,那么每一圈开始打印的位置是从左上角开始的。如果矩阵的行数是rows,列数是columns。则左上角的坐标是(0,0),(1,1),(2,2) … ,我们以(start,start)做为每一圈开始打印的位置。start从0开始。
让循环继续的条件是: cloumns > start * 2 && rows > start * 2
如何顺时针打印一圈
打印一圈分为四步:第一步从左到右打印一行;第二步从上到下打印一列;第三步从右到左打印一行;第四步从下到上打印一列。
但是,最后一圈有特殊情况:
如果最后一圈只有一行:因为第一步总是要走的,所以只走第一步。
如果最后一圈只有一列:走完第二步。
如果最后一圈至少有两行两列:走完第三步。
如果最后一圈至少有三行两列:走完第四步。
代码
#include <iostream>
// 打印矩阵的一圈
void PrintMatrixInCircle(int** numbers, int rows, int columns, int start)
{
// endX:横向边界, endY:纵向边界
int endX = columns - 1 - start;
int endY = rows - 1 - start;
// 从左往右打印一行
for (int i = start; i <= endX; ++i)
std::cout << numbers[start][i] << ' ';
// 如果当前矩阵有两行或以上,则从上到下打印一列
if (start < endY)
{
for (int i = start + 1; i <= endY; ++i)
std::cout << numbers[i][endX] << ' ';
}
// 如果当前矩阵有两行或以上,且不少于两列,则从右往左打印一行
if (start < endY && start < endX)
{
for (int i = endX - 1; i >= start; --i)
std::cout << numbers[endY][i] << ' ';
}
// 如果当前矩阵有三行或者以上,且不少于两列,则从下往上打印一列
if (start < endY - 1 && start < endX)
{
for (int i = endY - 1; i >= start + 1; --i)
std::cout << numbers[i][start] << ' ';
}
}
// 顺时针打印矩阵
void PrintMatrixClockWisely(int** numbers, int rows, int columns)
{
if (numbers == nullptr || columns <= 0 || rows <= 0)
return;
// start: 开始打印位置; 每一圈从(start,start)位置开始打印,0表示最外圈
int start = 0;
// 判断最内圈的条件: start == std::min(columns,rows) / 2
while (columns > start * 2 && rows > start * 2)
{
PrintMatrixInCircle(numbers, rows, columns, start);
++start;
}
}
int main()
{
// int matrix[1][5] = { 1,2,3,4,5 }; // 只有一行
// int matrix[5][1] = { {1},{2},{3},{4},{5} }; // 只有一列
// int matrix[3][4] = { {1,2,3,4}, {10,11,12,5}, {9,8,7,6} }; // 列多于行
int matrix[4][3] = { {1,2,3}, {10,11,4}, {9,12,5}, {8,7,6} }; // 行多于列
int rows = 4;
int columns = 3;
int *ptr_arr[rows]; //指针数组
for(int i = 0; i < rows; ++i)
{
ptr_arr[i] = matrix[i];
}
PrintMatrixClockWisely(ptr_arr, rows, columns);
return EXIT_SUCCESS;
}