题解
【入门】有趣的斜角
1 条题解
-
0
解题思路
先观察样例,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