剑指offer-顺时针打印矩阵

本文介绍了一种按顺时针方向打印矩阵中数字的方法,通过分层处理矩阵,逐层打印每一圈的元素,实现了从外向里的顺时针打印逻辑。文章详细解释了打印过程中的边界条件判断及循环终止条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
例如:
这里写图片描述
我们可以借助图形来帮助思考,如下图:
这里写图片描述
我们可以将打印分为一圈一圈的,
对于左图,6X6的矩阵,最后一圈有4个数字,左上角为(2,2),6>2X2;
对于右图,5X5的矩阵,最后一圈只有一个数字,左上角也为(2,2),5>2X2;
因此我们可将cols>srartX*2且rows>startY*2当做循环条件来打印每个圈:

void PrintMatrixClockwisely(int **numbers, int cols, int rows)
{
    if (numbers == NULL || cols <= 0 || rows <= 0)
        return;

    int start = 0;

    while (cols > start * 2 && rows > start * 2)
    {
        PrintMatrixInCircle(numbers, cols, rows, start);
        ++start;
    }
}

打印每圈又分为4步:
1. 从左到右打印一行
2. 从上到下打印一行
3. 从右到左打印一行
4. 从下到上打印一行

值得注意的是,最后一圈会退化成一行或只有一列,甚至只有一个数字:
如下图:
这里写图片描述
因此我们上面四步的循环还需要一定的判断条件,比如第二步的前提是终止的行号大于起始行号,其余步骤依次论推。
代码如下:

void PrintMatrixInCircle(int **numbers, int cols, int rows, int start)
{
    int endX = cols - 1 - start;
    int endY = rows - 1 - start;

    //从左到右打印一行
    for (int i = start; i <= endX; i++)
    {
        cout << numbers[start][i] << " ";
    }

    //从上到下打印一列
    if (start < endY)
    {
        for (int i = start + 1; i <= endY; i++)
        {
            cout << numbers[i][endX] << " ";
        }
    }

    //从右到左打印一行
    if (start < endX&&start < endY)
    {
        for (int i = endX-1; i >= start; i--)
        {
            cout << numbers[endY][i]<<" ";
        }
    }

    //从下到上打印一列
    if (start < endX&&start < endY - 1)
    {
        for (int i = endY - 1; i >= start + 1; i--)
        {
            cout << numbers[i][start] << " ";
        }
    }
}

我们测试也需要测各种情况:
如下

void Test(int cols, int rows)
{
    if (cols < 1 || rows < 1)
        return;

    int** numbers = new int*[rows];

    for (int i = 0; i < rows; ++i)
    {
        numbers[i] = new int[cols];
        for (int j = 0; j < cols; ++j)
        {
            numbers[i][j] = i * cols + j + 1;
        }
    }
    PrintMatrixClockwisely(numbers, cols, rows);
    printf("\n");

    for (int i = 0; i < rows; ++i)
        delete[](int*)numbers[i];
    delete[] numbers;
}



int main(int argc, char* argv[])
{
    /*  1   */
    Test(1, 1);

    /*
    1    2
    3    4
    */
    Test(2, 2);

    /*
    1
    2
    3
    4
    5
    */
    Test(1, 5);

    /*
    1    2
    3    4
    5    6
    7    8
    9    10
    */
    Test(2, 5);
    /*

    1    2    3

    4    5    6

    7    8    9

    10   11   12

    13   14   15

    */

    Test(3, 5);

    /*

    1    2    3    4    5

    */
    Test(5, 1);
    /*
    1    2    3    4    5

    6    7    8    9    10

    */

    Test(5, 2);
    /*
    1    2    3    4    5

    6    7    8    9    10

    11   12   13   14    15

    */

    Test(5, 3);

    system("pause");
    return 0;

}

结果:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值