前文廢話:這個問題據說是騰訊之前的一道筆試題,由於當時沒認真看,現在記不清這種矩陣是不是叫“蛇形回環矩陣”......請大家直接看圖1,就是那個樣子的矩陣。
問題描述:輸入一個N,實現N×N的蛇形回環矩陣(即圖1類型)
(N=5時的蛇形回環矩陣)
我們先把N為奇數和N為偶數的情況分開。先來看N=3、5、7時的該類矩陣是什么情況:
看上去彼此之間並無規律,對這道題最簡單粗暴的解法似乎就是構建一個二維數組,然后按人的正常思維向里填數字構建。
但是——如果用(最大數+1)減去每個數,那么這三個矩陣就變成了:
現在就有了規律。
而N為偶數時,彼此之間也是這樣的規律。
所以只要得到N=K-2時的矩陣,就能通過在原先的每行前添一列,后面添一列,然后上面添一行,下面添一行,就可以了。
為了實現這個能在前面插入的功能,構建二維的ArrayList。
實現的函數代碼如下:
1 //判斷N是偶數還是奇數,N為偶數時num=count,為奇數時num = count-1 2 public static void getArray(int num,int count){ 3 ArrayList<ArrayList> listAll = new ArrayList<ArrayList>(count);//二維Arraylist 4 if(num != count){//奇數時先構建最核心的1 5 ArrayList start = new ArrayList(count); 6 start.add(1); 7 listAll.add(start); 8 } 9 for(int i=0;i<num/2;i++){ 10 ArrayList listHead = new ArrayList();//構建要加的第一行 11 ArrayList listEnd = new ArrayList();//構建要加的最末行 12 int k; 13 if(num !=count) 14 k = 2*i+3; 15 else 16 k = 2*i+2; 17 for(int j=0;j<k;j++){ 18 listHead.add(k*k-j);//填充要加的第一行 19 listEnd.add((k-2)*(k-2)+k-1+j);//填充要加的最末行 20 if(j<(k-2)){//原有的每行加頭加尾 21 ArrayList listTem = new ArrayList(); 22 listTem = listAll.get(j); 23 listTem.add(0,(k-2)*(k-2)+1+j); 24 listTem.add(k*k-k-j); 25 listAll.set(j,listTem); 26 } 27 } 28 listAll.add(0,listHead);//加入第一行 29 listAll.add(listEnd);//加入最末行 30 } 31 //輸出 32 for(int i=0;i<count;i++){ 33 ArrayList listTem = new ArrayList(); 34 listTem = listAll.get(i); 35 for(Iterator iter = listTem.iterator();iter.hasNext();){ 36 int lastValue = count*count+1 - (int)iter.next(); 37 //沒有標准化格式的輸出 38 // System.out.print(lastValue+" "); 39 System.out.printf("%3d ",lastValue); 40 } 41 System.out.println(); 42 } 43 }
這里把N=偶數和N=奇數時分開構建開頭的情況。其實就矩陣來看,N為偶數與N為奇數之間也可以通過矩陣轉置來實現。但開頭分開也比較簡單實現,所以就用這種途徑了。完整代碼實現見github:https://github.com/Pengyiqing/java_practice