文章目录
- 💯前言
- 💯题目解析
- 💯第一种实现方式:我的初始做法
- 实现思路
- 优缺点分析
- 💯第二种实现方式:我的优化做法
- 实现思路
- 优缺点分析
- 💯第三种实现方式:老师的做法
- 实现思路
- 优缺点分析
- 💯对比与优化
- 对比分析
- 优化建议
- 💯总结
💯前言
- 在学习 C++ 编程中,矩阵处理是一类非常基础且重要的应用,特别是在数据处理、图像计算和科学计算等领域。矩阵转置作为最简单的矩阵变换之一,是我们需要掌握的基本技能。本次,我们通过一道矩阵转置的题目来深入解析其实现过程和优化方法,同时对比不同的实现方式,提炼出最优解法,并进行适当的知识扩展。
以下内容包括对题目的解析、两种代码实现的详细讲解、老师的实现方案以及它们的对比分析与优化建议,最终形成一篇完整的矩阵转置解决方案与思路详解。
C++ 参考手册
💯题目解析
B2106 矩阵转置
题目描述
输入一个 n × m n \times m n×m 的矩阵 A A A,输出它的转置矩阵 A T A^T AT。
输入格式
- 第一行包含两个整数 n n n 和 m m m,表示矩阵 A A A 的行数和列数。
- 1 ≤ n ≤ 100 1 \leq n \leq 100 1≤n≤100
- 1 ≤ m ≤ 100 1 \leq m \leq 100 1≤m≤100
- 接下来 n n n 行,每行 m m m 个整数,表示矩阵 A A A 的元素。相邻两个整数之间用单个空格隔开。
输出格式
输出 m m m 行,每行 n n n 个整数,为矩阵 A A A 的转置。相邻两个整数之间用单个空格隔开。
输入输出样例
-
输入:
3 3 1 2 3 4 5 6 7 8 9
-
输出:
1 4 7 2 5 8 3 6 9
解析
- 输入矩阵是一个 3 × 3 3 \times 3 3×3 的矩阵。
- 转置操作将矩阵的行变为列,列变为行。
- 转置后的矩阵大小为 3 × 3 3 \times 3 3×3,内容如下:
1 4 7 2 5 8 3 6 9
💯第一种实现方式:我的初始做法
#include <iostream>
using namespace std;int arr1[105][105];
int arr2[105][105];
int main()
{int m, n;cin >> m >> n;for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){cin >> arr1[i][j];}}for(int j = 0; j < n; j++){for(int i = 0; i < m; i++){arr2[j][i] = arr1[i][j];}}for(int j = 0; j < n; j++){for(int i = 0; i < m; i++){cout << arr2[j][i] << " ";}cout << endl;}return 0;
}
实现思路
- 定义两个数组:
arr1
用于存储输入矩阵;arr2
用于存储转置后的矩阵。
- 输入矩阵:
- 通过嵌套循环将矩阵的每个元素按行存储到
arr1
中。
- 通过嵌套循环将矩阵的每个元素按行存储到
- 进行转置:
- 遍历矩阵元素,按公式 A T [ j ] [ i ] = A [ i ] [ j ] A^T[j][i] = A[i][j] AT[j][i]=A[i][j] 填充转置矩阵
arr2
。
- 遍历矩阵元素,按公式 A T [ j ] [ i ] = A [ i ] [ j ] A^T[j][i] = A[i][j] AT[j][i]=A[i][j] 填充转置矩阵
- 输出转置矩阵:
- 遍历
arr2
,逐行输出。
- 遍历
优缺点分析
优点:
- 思路清晰,逻辑简单,易于理解。
- 使用两个数组分离输入矩阵与输出矩阵的存储,代码结构清晰。
缺点:
- 使用了两个二维数组,增加了额外的空间开销。
- 输出逻辑未处理行末多余的空格。
💯第二种实现方式:我的优化做法
#include <iostream>
using namespace std;int arr[105][105];
int main()
{int m, n;cin >> m >> n;for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){cin >> arr[i][j];}}for(int j = 0; j < n; j++){for(int i = 0; i < m; i++){cout << arr[i][j] << " ";}cout << endl;}return 0;
}
实现思路
- 省略了
arr2
数组,直接利用arr
进行转置。 - 输出时按转置逻辑直接从
arr
中读取数据。 - 输出矩阵时直接打印转置后的值,无需额外存储。
优缺点分析
优点:
- 相比第一种实现方式,节省了额外的数组存储空间。
- 代码更加简洁,减少了不必要的变量定义。
缺点:
- 同样未处理行末多余空格的问题。
💯第三种实现方式:老师的做法
#include <iostream>
using namespace std;const int N = 110;
int arr[N][N];
int m, n;int main()
{cin >> m >> n;for (int i = 0; i < m; i++){for (int j = 0; j < n; j++){cin >> arr[i][j];}}for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){cout << arr[j][i] << " ";}cout << endl;}return 0;
}
实现思路
- 定义了常量
N = 110
,设置矩阵的最大边界,确保足够空间存储矩阵。 - 使用全局变量
arr
存储矩阵,避免在函数内部重复定义。 - 输入矩阵后,直接利用转置逻辑输出矩阵,无需额外数组存储。
优缺点分析
优点:
- 与第二种实现方式相似,同样节省了空间,直接利用输入数组进行转置。
- 利用全局变量的方式,使得代码简洁易读,输入输出逻辑分明。
缺点:
- 同样存在输出行末多余空格的问题。
- 全局变量在复杂程序中可能引入意外的副作用。
💯对比与优化
对比分析
实现方式 | 空间复杂度 | 时间复杂度 | 易读性 | 可优化点 |
---|---|---|---|---|
第一种实现 | O ( n × m ) O(n \times m) O(n×m) | O ( n × m ) O(n \times m) O(n×m) | 简单明了 | 减少空间使用 |
第二种实现 | O ( 1 ) O(1) O(1) | O ( n × m ) O(n \times m) O(n×m) | 更简洁 | 修复多余空格 |
第三种实现 | O ( 1 ) O(1) O(1) | O ( n × m ) O(n \times m) O(n×m) | 清晰规范 | 避免全局变量 |
优化建议
-
去除行末多余空格:
输出逻辑可以通过条件判断避免行末多余空格:for (int j = 0; j < m; j++) {cout << arr[j][i];if (j < m - 1) cout << " "; }
-
输入输出优化:
在大数据量场景下,可以使用scanf
和printf
提高效率:scanf("%d %d", &m, &n); for (int i = 0; i < m; i++)for (int j = 0; j < n; j++)scanf("%d", &arr[i][j]);
-
避免全局变量:
将全局变量arr
改为局部变量,增强程序模块化能力。
💯总结
通过对这道矩阵转置题目的深入剖析,我们学习了三种不同的实现方法及其优缺点。随着实现方式的优化,我们逐渐减少了空间开销,使代码更高效简洁。最终,我们可以在满足题目要求的基础上,进一步提高代码的鲁棒性和扩展性。这类问题的解决,不仅让我们理解了矩阵操作的基本原理,也锻炼了对代码优化的思考能力。