1 題目描述
疫情期間,小明隔離在家,百無聊賴,在紙上寫數字玩。他發明了一種寫法:
給出數字個數 n (0 < n ≤ 999)和行數 m(0 < m ≤ 999),從左上角的 1 開始,按照順時針螺旋向內寫方式,依次寫出2,3,…,n,最終形成一個 m 行矩陣。
小明對這個矩陣有些要求:
每行數字的個數一樣多
列的數量盡可能少
填充數字時優先填充外部
數字不夠時,使用單個 * 號占位
2 輸入描述
兩個整數,空格隔開,依次表示 n、m
3 輸出描述
符合要求的唯一矩陣
4 用例
4.1 用例1
輸入
9 4
輸出
1 2 3
* * 4
9 * 5
8 7 6
4.2 用例2
輸入
3 5
輸出
1
2
3
*
*
5 題目分析·
考點:這道題考的是對二維數組的使用。
解析:題目中比較容易鉆牛角尖的描述是每行數字的個數一樣多
。這句實際上是矩陣的特點,可以忽略。讀完題目,我們發現有兩個問題需要解決
1. 確定矩陣的列數
2. 設計填充的算法
通過列的數量盡可能少
這個需求,我們可以想到,最少
的情況,即矩陣中填充的全都是數字。那么列數
= 填充的數字個數n
/行數
向上取整。
然后是如何填充,這就涉及到了二維數組的螺旋形遍歷。我們可以想象一個人在背包容量限制下,在順時針繞圈撿東西,當不為0,則為已撿過,即換方向撿。
6 Java代碼
根據5中的思路,我們可以寫出如下代碼(代碼中給出了詳細的注釋):
public class SpiralMatrix {public static void main(String[] args) {//這里n和m可以修改為使用Scanner從控制臺讀取輸入int n = 120;int m = 7;int columnCount=Math.ceilDiv(n,m);int[][] matrix = new int[m][columnCount];fillSpiral(matrix,n);for (int i = 0; i < m; i++) {for (int j = 0; j < columnCount; j++) {System.out.printf("%2s ", matrix[i][j] == 0 ? "*" : matrix[i][j]);}System.out.println();}}public static void fillSpiral(int[][] matrix, int total) {// 將要填充的數字,從1開始int num = 1;// 方向變量,四個元素分別表示:向右,向下,向左,向上int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};// 初始化方向變量的索引,0表示初始方向為向右int dir = 0;// 初始化行列索引int row = 0, col = 0;// 繼續填充,直到所有的數字被填充完while (num <= total) {// 將數字填充到矩陣的當前位置,然后數字加1matrix[row][col] = num++;// 嘗試按照當前方向去獲取新的行列索引int newRow = row + directions[dir][0];int newCol = col + directions[dir][1];// 檢查新的行列索引是否超出矩陣的邊界,或者該位置已經被填充過// 如果是,則將方向變量的索引加1(取模為了形成循環:向右,向下,向左,向上)if (newRow < 0 || newRow >= matrix.length || newCol < 0 || newCol >= matrix[0].length || matrix[newRow][newCol] != 0) {dir = (dir + 1) % 4;}// 根據新的方向更新行列索引row += directions[dir][0];col += directions[dir][1];}}
}