《剑指Offer》面试题29:顺时针打印矩阵
1 题目
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
2 问题分析
<1>首先理解问题,借用图形将问题抽象化为具体。
/*
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
*/
<2>如果把顺时针打印矩阵想象成打印一个又一个的圈,可以利用循环的方法来实现。分析循环开始和循环结束的条件
每次打印一个圈,起点位置的坐标值相等,即 startX = startY。并且满足
columns >= startX*2) && (rows >= startY*2)
<3>在具体分析实现打印一个圈,又需要哪些步骤,要不要考虑边界条件。其中,由于最后一个圈的矩阵会发生退化,要确定每一步的执行条件。
PS:拿到问题,先至上向下分析问题,在从下向上解决问题。
3 代码
#include "iostream"
#include "cstdlib"
using namespace std;
//问题:顺时针打印矩阵
bool Print_array_clockwise(int** numbers, int columns, int rows);
void Print_array_circle(int** numbers, int columns, int rows, int start);
//功能:顺时针方式打印数组
//输入:numbers矩阵首地址, columns 列数, rows 行数
//输出:false 参数无效, true 成功
bool Print_array_clockwise(int** numbers, int columns, int rows)
{
//1.检查参数的有效性
if ( (numbers == nullptr) || (columns <= 0) || (rows <= 0) )
{
return false;
}
int start = 0; //定义起点(start, start)
//2.循环方式顺时针打印矩阵,每次循环打印一圈
while ( (columns >= start*2) && (rows >= start*2) )
{
Print_array_circle(numbers, columns, rows, start); //打印一圈
start++;
}
return true;
}
//打印一圈元素,分成四个步骤。由于打印到最后一个矩阵的时候,矩阵会退化(这时候不确定要分成几步),所以要明确每一步的执行条件
void Print_array_circle(int** numbers, int columns, int rows, int start)
{
int endX = columns - 1 - start; //终点列坐标
int endY = rows - 1 - start; //终点行坐标
//1.从左向右打印列元素
if (start <= endX)
{
for (int i = start;i <= endX;i++)
{
cout << numbers[start][i] << ",";
}
}
//2.从上往下打印行元素
if (start < endY)
{
for (int i = start+1;i <= endY;i++)
{
cout << numbers[i][endX] << ",";
}
}
//3.从右向左打印列元素
if ( (start < endX) && (start < endY) )
{
for (int i = endX-1;i >= start;i--)
{
cout << numbers[endY][i] << ",";
}
}
//4.从下向上打印行元素
if ( (start < endX) && (start+1 < endY) )
{
for (int i = endY-1; i >= start+1;i--)
{
cout << numbers[i][start] << ",";
}
}
}
void Test(int columns, int rows)
{
int** numbers = new int*[rows];
for(int i = 0; i < rows; ++i)
{
numbers[i] = new int[columns];
for(int j = 0; j < columns; ++j)
{
numbers[i][j] = i * columns + j + 1;
}
}
Print_array_clockwise(numbers, columns, rows);
cout << endl;
}
int main(int argc, char const *argv[])
{
Test(3, 3); //3行3列
Test(1, 5); //5行1列
Test(5, 1); //1行5列
return 0;
}