PAT 乙级 1050.螺旋矩阵

题目来源

本题要求将给定的 N 个正整数按非递增的顺序,填入“螺旋矩阵”。所谓“螺旋矩阵”,是指从左上角第 1 个格子开始,按顺时针螺旋方向填充。要求矩阵的规模为 m 行 n 列,满足条件:m×n 等于 N;mn;且 mn 取所有可能值中的最小值。

输入格式:

输入在第 1 行中给出一个正整数 N,第 2 行给出 N 个待填充的正整数。所有数字不超过 1,相邻数字以空格分隔。

输出格式:

输出螺旋矩阵。每行 n 个数字,共 m 行。相邻数字以 1 个空格分隔,行末不得有多余空格。

输入样例:

12
37 76 20 98 76 42 53 95 60 81 58 93
 

输出样例:

98 95 93
42 37 81
53 20 76
58 60 76

分析:

1. 确定m和n:

N个正整数,按照大到小的顺序,顺时针螺旋方向填充,形成一个m行n列的矩阵

而且:m×n 等于 N;mn;且 mn 取所有可能值中的最小值。

也就是说,m和n都是N的两个因数,m和n的差值尽可能小,m≥n

对N开方运算,得到的结果转成int

比如,N = 12,12在 3和 42 之间

那么对N开方,向下取整,得到的一个结果,就是N的因数之一

所以,n = (int) √N , m = N / n

2. 数组排序

数据用一个一维数组接收,降序排序

3. 生成螺旋矩阵:

假定 m = 4, n = 3

那么我们就生成一个4行3列的二维矩阵:

(00),(00),(00)

(00),(00),(00)

(00),(00),(00)

(00),(00),(00)

按照规律把一维数组arr的数据放入二维数组matrix

left = 0, right = n - 1 = 2;

up = 0, down = m - 1 = 3;

(1) 先处理最上方,从左到右

up不变,i 的范围是 [left, right] 

赋值给  matrix[up][i]  得到

(98),(95),(93)

(00),(00),(00)

(00),(00),(00)

(00),(00),(00)

第一行处理完了,up++

判断up是否大于down,如果大于,说明已经处理完毕了,可以退出循环

(2) 然后处理最右边,从右上到右下 

得到

(98),(95),(93)

(00),(00),(81)

(00),(00),(76)

(00),(00),(76)

(3) 接着处理最下边,从右到左

得到

(98),(95),(93)

(00),(00),(81)

(00),(00),(76)

(58),(60),(76)

(4) 然后处理最左边一列,从下到上得到

(98),(95),(93)

(42),(00),(81)

(53),(00),(76)

(58),(60),(76)

这一轮循环就结束了,接着从 (1)开始

需要注意的边界(退出循环):

(1)中处理完第一行,up++,判断up与down的关系

(2)中处理完最右边一列,right--,判断right与left的关系

(3)中处理完最下面一行,down--,判断down与up的关系

(4)中处理完最左边一列,left++,判断left与right的关系

如果出现left>right,up>down等类似情况,就终止循环

4. 输出二维矩阵matrix

C++实现:

这里用一个变量cnt来记录一维数组arr的索引

为的是按照顺序,把arr[cnt]赋值到二维矩阵matrix中

  1 #include <iostream>
  2 #include <vector>
  3 #include <algorithm>
  4 #include <cmath>
  5 using namespace std;
  6 int getN(int N) {
  7     int i = sqrt((double)N);
  8     while (i >= 1) {
  9         if (N%i == 0) {
 10             return i;
 11         }
 12         i--;
 13     }
 14     return 1;
 15 }
 16 
 17 
 18 bool cmp(int& a, int& b) {
 19     return a > b;
 20 }
 21 /*
 22 12
 23 37 76 20 98 76 42 53 95 60 81 58 93
 24 */
 25 
 26 int main() {
 27 
 28     int N;
 29     cin >> N;
 30     int n = getN(N);
 31     int m = N / n;
 32     vector<int> arr(N);
 33 
 34 
 35     for (int i = 0; i < N; ++i) {
 36         cin >> arr[i];
 37     }
 38     sort(arr.begin(), arr.end(), cmp);
 39     
 40     vector <vector<int> > matrix(m, vector<int>(n));
 41 
 42     int left = 0;
 43     int right = n - 1;
 44     int up = 0;
 45     int down = m - 1;
 46     int cnt = 0;    // arr的索引
 47 
 48     while (true) {
 49         // 从左往右的一行
 50         for (int i = left; i <= right; ++i) {
 51             matrix[up][i] = arr[cnt];
 52             cnt++;
 53         }
 54         // 上边界大于下边界
 55         up++;
 56         if (up > down) {
 57             break;
 58         }
 59 
 60         // 从右上往右下,靠右的一行
 61         for (int i = up; i <= down; ++i) {
 62             matrix[i][right] = arr[cnt];
 63             cnt++;
 64         }
 65         // 右边界小于左边界
 66         right--;
 67         if (right < left) {
 68             break;
 69         }
 70         // 从右下往左下,底下的一行
 71         for (int i = right; i >= left; --i) {
 72             matrix[down][i] = arr[cnt];
 73             cnt++;
 74         }
 75         // 如果下边界小于边界
 76         down--;
 77         if (down < up) {
 78             break;
 79         }
 80         // 左下到左上,靠左的一行
 81         for (int i = down; i >= up; --i) {
 82             matrix[i][left] = arr[cnt];
 83             cnt++;
 84         }
 85         // 如果左边界大于右边界
 86         left++;
 87         if (left > right) {
 88             break;
 89         }
 90     }
 91     
 92     for (int i = 0; i < m; ++i) {
 93         for (int j = 0; j < n; ++j) {
 94             if (j != 0) {
 95                 cout << ' ';
 96             }
 97             cout << matrix[i][j];
 98         }
 99         if (i != m - 1) {
100             cout << endl;
101         }
102     }
103 
104     return 0;
105 }

Java实现:






猜你喜欢

转载自www.cnblogs.com/47Pineapple/p/12793887.html
今日推荐