top1编程
← 返回题目
题解

【入门】有趣的斜角

1 条题解

  • 0
    @ 2026-8-1 11:16:49

    解题思路

    先观察样例,n=4 时输出的方阵是:

        1    5    8   10
        5    2    6    9
        8    6    3    7
       10    9    7    4
    

    这个方阵有一个很明显的特点:沿主对角线对称。 主对角线就是左上角到右下角那条线(1、2、3、4)。你会发现 a[i][j] 和 a[j][i] 总是同一个数,比如第 1 行第 2 列是 5,第 2 行第 1 列也是 5。

    所以我们可以先只填右上三角(含主对角线),再沿主对角线对称复制到左下三角,这样两次就能得到整个方阵。

    数字又是按什么顺序填的呢?看右上三角:

    • 主对角线(第 1 条斜线):1、2、3、4
    • 第 2 条斜线(主对角线右上方一条):5、6、7
    • 第 3 条斜线:8、9
    • 第 4 条斜线:10

    规律就是:数字按"斜线"从主对角线向右上一条一条地填,每条斜线上的数字都是连续的。 第 k 条斜线上有 n-k 个数(k 从 0 开始,k=0 是主对角线,k=1 是它右上的下一条)。

    用代码实现时用两层循环:

    • 外层循环 k 表示第几条斜线;
    • 内层循环 i 表示这条斜线上的第几个格子。

    第 k 条斜线上的第 i 个格子,就是第 i 行、第 i+k 列,即 a[i][i+k]。

    以 n=4 为例走一遍:

    • k=0(主对角线):填 a[0][0]=1、a[1][1]=2、a[2][2]=3、a[3][3]=4
    • k=1(第 2 条斜线):填 a[0][1]=5、a[1][2]=6、a[2][3]=7
    • k=2(第 3 条斜线):填 a[0][2]=8、a[1][3]=9
    • k=3(第 4 条斜线):填 a[0][3]=10

    右上三角填完后,再沿主对角线对称复制:把 a[i][j] 的值抄到 a[j][i](a[j][i] = a[i][j]),整个方阵就完成了。

    最后输出时,题目要求每个数字占 5 个字符宽度,我们使用 setw(5) 来实现。 setw 来自 <iomanip> 库,作用是让每个数至少占 5 个格子,不够的位数在左边补空格,这样数字就能整整齐齐地对齐。

    参考代码

    // 题目:有趣的斜角(入门)
    // 思路:数字按"斜线"从主对角线向右上一条一条填,
    //       每条斜线上的数连续递增,整个矩阵沿主对角线对称。
    // 用到的库:iostream(输入输出)、iomanip(setw 设置场宽)
    #include <iostream>
    #include <iomanip>
    using namespace std;
    
    int main()
    {
        int n;
        cin >> n;          // 输入边长 n(1 < n < 10)
    
        int a[15][15];     // 存储数字图形的二维数组
        int num = 1;       // 当前要填的数字,从 1 开始
    
        // k 表示第几条斜线:k=0 是主对角线,k=1 是它右上的下一条……
        for (int k = 0; k < n; k++)
        {
            // 第 k 条斜线共有 n-k 个格子,i 表示第几个
            for (int i = 0; i < n - k; i++)
            {
                int j = i + k;  // 第 k 条斜线上的格子是第 i 行第 i+k 列
                a[i][j] = num;  // 按顺序填数字
                num++;
            }
        }
    
        // 对称复制:把右上三角的数抄到左下三角
        // 因为 a[i][j] = a[j][i],图形沿主对角线对称
        for (int i = 0; i < n; i++)
        {
            for (int j = i + 1; j < n; j++)
            {
                a[j][i] = a[i][j];
            }
        }
    
        // 输出:每行 n 个数,每个数占 5 个字符宽度(setw(5))
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                cout << setw(5) << a[i][j];
            }
            cout << endl;   // 每行末尾换行
        }
    
        return 0;
    }
    

    复杂度分析

    • 时间复杂度:填数用两层循环,一共填了 n×n 个格子,所以是 O(n²)。
    • 空间复杂度:开了一个 n×n 的二维数组,所以是 O(n²)。
    • n 最大只有 9(1<n<10),规模非常小,程序运行飞快。
    • 1