算法分析:方陣的主對角線之上稱爲“上三角”。

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("");
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章