演算法分析:方陣的主對角線之上稱為“上三角”。
4、方陣的主對角線之上稱為“上三角”。
請你設計一個用於填充n階方陣的上三角區域的程式。填充的規則是:使用1,2,3….的自然數列,從左上角開始,按照順時針方向螺旋填充。
例如:當n=3時,輸出:
1 2 3
6 4
5
當n=4時,輸出:
1 2 3 4
9 10 5
8 6
7
當n=5時,輸出:
1 2 3 4 5
12 13 14 6
11 15 7
10 8
9
程式執行時,要求使用者輸入整數n(3~20)
程式輸出:方陣的上三角部分。
要求格式:每個資料寬度為4,右對齊。
思路解析
拿到這樣一個題目,很明顯是一個找規律的題目,既然是有規律的,那自然就好解了。
下面,我來給大家拆分一下,你也許就發現了點什麼,首先來看這張圖
從這個圖中再來分析2個點。
第一個點:把整個輸出結果按層拆分,例如:
當n=4時,1 2 3 4 5 6 7 8 9為最外層第一層,10為第二層
當n=5時,1 2 3 4 5 6 7 8 9 10 11 12為最外層第一層,13 14 15為第二層
當n=6時,
1 2 3 4 5 6
15 16 17 18 7
14 21 19 8
13 20 9
12 10
11
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 為最外層第一層,16 17 18 19 20 21為第二層
以此類推
第二個點:在每一層中在進行拆分,從上面的分析看出,每一層可以分成3份,每一份為n-1;
有了這樣一套整體的劃分和規律,在來分析一下下面這串程式碼。
//n為我們人為輸入的數
//定義一個二維陣列存放變數值
int a[][] = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = i; j < n - 1 - i * 2; j++)
{
a[i][j] = k;
k++;
}
for (int j = i; j < n - i * 2 - 1 ; j++) {
a[j][n - 1 - i - j] = k;
k++;
}
for (int j = i; j < n - 2 * i - 1; j++) {
a[n - 1 - i - j][i] = k;
k++;
}
}
外面的for迴圈即時我們前面分析的層。我們還是例如:
當n = 4時。二維陣列的分佈情況,暫時還未填充資料
a[0][0] =null a[0][1] =null a[0][2]=null a[0][3]=null
a[1][0] =null a[1][1] =null a[1][2]=null a[1][3]=null
a[2][0] =null a[2][1] =null a[2][2]=null a[2][3]=null
a[3][0] =null a[3][1] =null a[3][2]=null a[3][3]=null
有人說,當n=4時只有2層,這個for迴圈不是會執行4次嗎,不要著急,我們在for迴圈裡面還可以來進行限制嘛。
裡面的3個for迴圈一一來分析:主要是來控制他的輸出格式,而輸出的數字,由二維陣列控制。
內部!第一個for迴圈
此時假設後面的2個for迴圈已經執行完,則執行完後他賦值的引數如下:(為了方便排版001代表1)
a[0][0] =001 a[0][1] =002 a[0][2]=003 a[0][3]=000
a[1][0] =000 a[1][1] =000 a[1][2]=000 a[1][3]=000
a[2][0] =000 a[2][1] =000 a[2][2]=000 a[2][3]=000
a[3][0] =000 a[3][1] =000 a[3][2]=000 a[3][3]=000
第二個for迴圈
執行完後他賦值的引數如下:
a[0][0] =001 a[0][1] =002 a[0][2]=003 a[0][3]=004
a[1][0] =000 a[1][1] =000 a[1][2]=005 a[1][3]=000
a[2][0] =000 a[2][1] =006 a[2][2]=000 a[2][3]=000
a[3][0] =000 a[3][1] =000 a[3][2]=000 a[3][3]=000
第三個for迴圈
執行完後他賦值的引數如下:
a[0][0] =001 a[0][1] =002 a[0][2]=003 a[0][3]=004
a[1][0] =009 a[1][1] =000 a[1][2]=005 a[1][3]=000
a[2][0] =008 a[2][1] =006 a[2][2]=000 a[2][3]=000
a[3][0] =007 a[3][1] =000 a[3][2]=000 a[3][3]=000
執行到這裡n=4的結果已經出來了,只是跟題目的輸出還有出入
“`
採用此迴圈輸出,過濾到為0的即可得到n=4的結果
a[0][0] =001 a[0][1] =002 a[0][2]=003 a[0][3]=004
a[1][0] =009 a[1][1] =000 a[1][2]=005
a[2][0] =008 a[2][1] =006
a[3][0] =007
做到這裡這道題基本已經完工,但是顯然還有瑕疵,細心的同學可能已經發現,當n=4時,第二層的數10並沒有賦值,當n=5時所有數完整輸出。那我們猜想是不是偶數最中間的數都不會填充呢?多帶入幾個到以上演算法,很容易發現當(n - 1) % 3 == 0,中間的數不會填充。想到這裡,
if ((n - 1) % 3 == 0)
a[(n - 1) / 3][(n - 1) / 3] = k;
2句程式碼解決這個問題。
最終完整程式碼
public class Test{
public static void main(String[] args) {
//鍵盤輸入
Scanner sc = new Scanner(System.in);
System.out.println("put n!");
//n代表當前的迴圈數
int n = sc.nextInt();
int k = 1;
//定義一個二維陣列存放變數值
int a[][] = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = i; j < n - 1 - i * 2; j++)
{
a[i][j] = k;
k++;
}
for (int j = i; j < n - i * 2 - 1; j++) {
a[j][n - 1 - i - j] = k;
k++;
}
for (int j = i; j < n - 2 * i - 1; j++) {
a[n - 1 - i - j][i] = k;
k++;
}
}
if ((n - 1) % 3 == 0)
a[(n - 1) / 3][(n - 1) / 3] = k;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (a[i][j] == 0)
continue;
if (a[i][j] < 10)
System.out.print(a[i][j] + " ");
else if (a[i][j] < 100)
System.out.print(a[i][j] + " ");
else
System.out.print(a[i][j] + " ");
}
System.out.println("");
}
}
}