矩阵顺时针遍历
题目:输入矩阵行和列,要求能够打印出从1开始顺时针自增的矩阵,以m=5,n=4为例,输出如下矩阵
1 2 3 4
14 15 16 5
13 20 17 6
12 19 18 7
11 10 9 8
重点:遵循的原则是一层一层去遍历,每一层有4提条边(顶top/右right/下bottom/左left),每一段的遍历遵循左闭右开的原则,如果遍历到最后一圈,发现只有一条边或者一个点,需要单独处理下
m=4,n=6,遍历如下:
m=5,n=3,遍历如下
代码实现
#include <iostream>
#include <vector>
using namespace std;
void showMatrix(int m, int n){
vector<vector<int>> a(m, vector<int>(n,0));
int left = 0, top = 0, right = n-1, bottom = m-1;
int val = 1;
while(left < right && top < bottom){
// 顶部从左到右
for(int k = left; k < right; k++){
a[top][k] = val++;
}
// 右侧从上到下
for(int k = top; k < bottom; k++){
a[k][right] = val++;
}
// 底部从右到左
for(int k = right; k > left; k--){
a[bottom][k] = val++;
}
// 左侧从下到上
for(int k = bottom; k > top; k--){
a[k][left] = val++;
}
left += 1;
right -= 1;
top += 1;
bottom -= 1;
}
if(left == right && top < bottom){ // 剩下一列待填充
for(int k = top; k <= bottom; k++){
a[k][left] = val++;
}
}else if(left < right && top == bottom){ // 剩下一行待填充
for(int k = left; k <= right; k++){
a[top][k] = val++;
}
}else if(left == right && top == bottom){ // 剩下一个点待填充
a[left][top] = val++;
}
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
cout << a[i][j] << "\t";
}
cout << endl;
}
}
int main()
{
showMatrix(5,4);
return 0;
}
输出结果
如果是 m == n 那就是正方形
给定一个正整数 n,生成一个包含 1 到 n 2 n^2 n2 总共 n 2 n^2 n2 各元素,且元素按顺时针顺序螺旋排列的正方形矩阵。例如 n=3
前面的代码里面的m都该成n就行,同时因为是正方形,最后一圈不存在只有一行或者一列,当n为奇数的时候,只剩下最中心的一个点没有填充,单独处理即可。
n=3
n=4
#include <iostream>
#include <vector>
using namespace std;
void showMatrix(int n){
vector<vector<int>> a(n, vector<int>(n,0));
int left = 0, top = 0, right = n-1, bottom = n-1;
int val = 1;
while(left < right && top < bottom){
// 顶部从左到右
for(int k = left; k < right; k++){
a[top][k] = val++;
}
// 右侧从上到下
for(int k = top; k < bottom; k++){
a[k][right] = val++;
}
// 底部从右到左
for(int k = right; k > left; k--){
a[bottom][k] = val++;
}
// 左侧从下到上
for(int k = bottom; k > top; k--){
a[k][left] = val++;
}
left += 1;
right -= 1;
top += 1;
bottom -= 1;
}
// if(left == right && top < bottom){ // 剩下一列待填充
// for(int k = top; k <= bottom; k++){
// a[k][left] = val++;
// }
// }else if(left < right && top == bottom){ // 剩下一行待填充
// for(int k = left; k <= right; k++){
// a[top][k] = val++;
// }
// }else if(left == right && top == bottom){ // 剩下一个点待填充
// a[left][top] = val++;
// }
if(n % 2 == 1){ // 当n为奇数的时候,这里只剩一个点待填充,正方形不存在最后一行或者一列待填充的情况
a[n/2][n/2] = val++;
}
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
cout << a[i][j] << "\t";
}
cout << endl;
}
}
int main()
{
showMatrix(3);
return 0;
}
矩阵对角线遍历
题目:输入矩阵行和列,要求能够打印出从1开始对角线自增的矩阵,以m=5,n=4为例,输出如下矩阵
从最左上角开始,按对角线方式一直遍历到最右下角结束。到达边界就需要改变遍历顺序(向上或者向下),用个bool变量标识遍历顺序。
遵循原则:
往上:行-1,列+1;可能会超过上边界或者右边界,超过上边界,行+1,列不变,超过右边界,行+2,列-1
往下:行+1,列-1;可能会超过下边界或者左边界,超过下边界,行-1,列+2,超过左边界,行不变,列+1
遍历图如下:
#include <iostream>
#include <vector>
using namespace std;
void showMatrix(int m, int n){
vector<vector<int>> a(m, vector<int>(n,0));
bool up = true;
int row = 0, col = 0;
int val = 1;
while(row < m || col < n){ // 没有到达最右下角位置,则一直循环
if(0 <= row && row < m && col < n && 0 <= col){
a[row][col] = val++;
}
if(up){ // 斜向上遍历 行-1,列+1
row -= 1;
col += 1;
if(row < 0){ // 超过上边界
row += 1;
up = false; // 需要往斜向下遍历
}else if(col > n-1){ // 超过右边界
col -= 1;
row += 2;
up = false; // 需要往斜向下遍历
}
}else{ // 斜向下遍历 行+1,列-1
row += 1;
col -= 1;
if(row > m-1){ // 超过下边界
row -= 1;
col += 2;
up = true; // 需要往斜向上遍历
}else if(col < 0){ // 超过左边界
col += 1;
up = true; // 需要往斜向上遍历
}
}
}
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
cout << a[i][j] << "\t";
}
cout << endl;
}
}
int main()
{
showMatrix(3,5);
return 0;
}
矩阵旋转
题目:输入方阵形状n,要求能够将方阵顺时针旋转90度,以n=4为例,变化如下矩阵
遵循原则:和螺旋矩阵一样,一层一层来;每层先把顶部行暂存起来,然后依次旋转复制
#include <iostream>
#include <vector>
using namespace std;
void show(vector<vector<int>> a){
int n = a.size();
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
cout << a[i][j] << "\t";
}
cout << endl;
}
}
void showMatrix(vector<vector<int>> a){
int n = a.size();
int left = 0, right = n-1, top = 0, bottom = n-1;
vector<int> topEage(n,0); // 顶部暂存数组
vector<int> tmp(n, 0); // 取数据暂存
while(left < right && top < bottom){
// 暂存顶部边的数据,放到topEage数组中
int i = 0;
for(int k = left; k < right; k++){
topEage[i] = a[top][k];
i++;
}
i = 0;
// 左边数据取出来,放到tmp中
for(int k = bottom; k > top; k--){
tmp[i] = a[k][left];
i++;
}
// tmp复制到顶部边上
i = 0;
for(int k = left; k < right; k++){
a[top][k] = tmp[i];
i++;
}
cout << "copy to top" << endl;
show(a);
// 底部数据取出来,放到tmp中
i = 0;
for(int k = right; k > left; k--){
tmp[i] = a[bottom][k];
i++;
}
// tmp复制到左部边上
i = 0;
for(int k = bottom; k > top; k--){
a[k][left] = tmp[i];
i++;
}
cout << "copy to left" << endl;
show(a);
// 右部数据取出来,放到tmp中
i = 0;
for(int k = top; k < bottom; k++){
tmp[i] = a[k][right];
i++;
}
// tmp复制到底部边上
i = 0;
for(int k = bottom; k > top; k--){
a[bottom][k] = tmp[i];
i++;
}
cout << "copy to bottom" << endl;
show(a);
// 顶部数据在topEage中,复制到右部边上
i = 0;
for(int k = top; k < bottom; k++){
a[k][right] = topEage[i];
i++;
}
cout << "copy to right" << endl;
show(a);
left += 1;
right -= 1;
top += 1;
bottom -= 1;
}
cout << "final" << endl;
show(a);
}
vector<vector<int>> getMatrix(int n){ // 生成自增长螺旋矩阵
vector<vector<int>> a(n, vector<int>(n, 0));
int left = 0, right = n-1, top = 0, bottom = n-1;
int val = 1;
// left/right 是列维度
// top/bottom 是行维度
while(left < right && top < bottom){
for(int k = left; k < right; k++){ // 顶部
a[top][k] = val++;
}
for(int k = top; k < bottom; k++){ // 右部
a[k][right] = val++;
}
for(int k = right; k > left; k--){ // 底部
a[bottom][k] = val++;
}
for(int k = bottom; k > top; k--){ // 左部
a[k][left] = val++;
}
left += 1;
right -= 1;
top += 1;
bottom -= 1;
}
if(n%2==1){
a[n/2][n/2] = val++;
}
return a;
}
int main()
{
int n = 4;
vector<vector<int>> a = getMatrix(n);
cout << "start" << endl;
show(a);
showMatrix(a);
return 0;
}