[算法]循環打印矩陣,蛇形矩陣專題

1. 循環打印矩陣

比方提供如下矩陣:java

按照以下順序打印出來:優化

1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10spa

這道題直接寫也沒問題,就是特別容易出錯,稍不留意就寫錯,並且這類題型我想要一種普適性的解法。指針

我想到的一種方法就是一圈一圈打印,從外到內,咱們肯定一個矩形,一般經過左上角的座標和右下角的座標便可,即(tR,tC)和(dR,dC),咱們先寫出打印一圈的方法,而後循環調用,若是咱們發現左上角的座標跑到了右下角座標的右邊或者下邊,整個過程就中止,這樣額外的空間複雜度是O(1)。No bibi,show me the code.code

package com.darrenchan;

/**
 * 轉圈打印矩陣
 * @author Think
 *
 */
public class SheXingPrint2 {
    public static void main(String[] args) {
        int[][] m = new int[][]{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
        
        int tR = 0, tC = 0, dR = 0, dC = 3;
        while(tR <= dR && tC <= dC){
            printEdge(m, tR++, tC++, dR--, dC--);
        }
    }
    
    public static void printEdge(int[][] m, int tR, int tC, int dR, int dC){
        if(tR == dR){
            for (int i = tC; i <= dC; i++) {
                System.out.print(m[tR][i] + " ");
            }
        }else if(tC == dC){
            for (int i = tR; i <= dR; i++) {
                System.out.print(m[i][tC] + " ");
            }
        }else{
            int curRow = tR;
            int curCol = tC;
            while(curCol != dC){
                System.out.print(m[tR][curCol] + " ");
                curCol++;
            }
            while(curRow != dR){
                System.out.print(m[curRow][dC] + " ");
                curRow++;
            }
            
            while(curCol != tC){
                System.out.print(m[dR][curCol] + " ");
                curCol--;
            }
            
            while(curRow != tR){
                System.out.print(m[curRow][tC] + " ");
                curRow--;
            }
            
        }
    }
}

2. 蛇形矩陣

給出一個數字,比方是4,直接生成以下矩陣:blog

思路和上一個相似,只是稍微改一下便可:get

package com.darrenchan;

/**
 * 打印蛇形矩陣
 * @author Think
 *
 */
public class SheXingPrint3 {
    public static int num = 1;
    public static void main(String[] args) {
        //給出多大的數字,就構造多大的矩陣
        int length = 4;
        int[][] m = new int[length][length];

        int tR = 0, tC = 0, dR = m.length - 1, dC = m[0].length - 1;
        while (tR <= dR && tC <= dC) {
            generateEdge(m, tR++, tC++, dR--, dC--);
        }
        
        for (int i = 0; i < m.length; i++) {
            for (int j = 0; j < m[i].length; j++) {
                System.out.print(m[i][j] + "\t");
            }
            System.out.println();
        }
    }

    public static void generateEdge(int[][] m, int tR, int tC, int dR, int dC) {
        if(tR == dR){//處理length爲奇數,最中間一個元素
            m[tR][tC] = num;
        }else{
            int curRow = tR;
            int curCol = tC;
            while(curCol != dC){
                m[tR][curCol] = num;
                num++;
                curCol++;
            }
            while(curRow != dR){
                m[curRow][dC] = num;
                num++;
                curRow++;
            }
            while(curCol != tC){
                m[dR][curCol] = num;
                num++;
                curCol--;
            }
            while(curRow != tR){
                m[curRow][tC] = num;
                num++;
                curRow--;
            }
        }
    }
}

 

3. 雙循環打印矩陣

一個起始點在左上角,和之前同樣,順時針走,另外一個起始點在右下角,也是順時針走,別人走過的,就不能重複走了。it

比方class

打印出:1 2 3 4 import

打印出:1 2 3 6 5 4 7 8 9 

打印出:1 2 3 4 8 12 11 10 7 6 5 9 13 14 15 16 

這道題的思路其實和上面第一個差很少,我仍是採用的一圈一圈打印的思路,只不過原來一個指針打印一圈轉4個方向,如今有兩個指針,每一個轉2個方向,第一次轉兩個方向,第二次轉另兩個方向,依次類推。

其實這道題還能夠進一步優化,由於兩個指針徹底關於矩陣中心點對稱,因此肯定一個,另外一個就肯定了。這裏須要一個矩陣來記錄該點是否已經走過。

代碼以下:

package com.darrenchan;

import java.util.LinkedList;
import java.util.List;

/**
 * 雙蛇形打印
 * @author Think
 *
 */
public class SheXingPrint4 {
    public static int num = 1;
    public static void main(String[] args) {
        //給出多大的數字,就構造多大的矩陣
        int length = 5;
        int[][] m = new int[length][length];
        int temp = 1;
        for (int i = 0; i < m.length; i++) {
            for (int j = 0; j < m[i].length; j++) {
                m[i][j] = temp++;
            }
        }

        int[][] visited = new int[m.length][m[0].length];//0是沒有訪問過,1是訪問過
        
        List<Integer> list1 = new LinkedList<>();
        List<Integer> list2 = new LinkedList<>();        
        
        int tr = 0;
        int tc = 0;
        int dr = m.length - 1;
        int dc = m[0].length - 1;
        
        int count = 1;
        while(tr <= dr && tc <= dc){
            
            if(count % 2 == 1){
                int curRow1 = tr;
                int curCol1 = tc;
                int curRow2 = dr;
                int curCol2 = dc;
                while(curCol1 != dc && curCol2 != tc){
                    if(visited[curRow1][curCol1] == 0 && visited[curRow2][curCol2] == 0){
                        visited[curRow1][curCol1] = 1;
                        list1.add(m[curRow1][curCol1]);
                        curCol1++;
                        visited[curRow2][curCol2] = 1;
                        list2.add(0, m[curRow2][curCol2]);
                        curCol2--;
                    }else{
                        break;
                    }
                }
                
                while(curRow1 != dr && curRow2 != tr){
                    if(visited[curRow1][curCol1] == 0 && visited[curRow2][curCol2] == 0){
                        visited[curRow1][curCol1] = 1;
                        list1.add(m[curRow1][curCol1]);
                        curRow1++;
                        visited[curRow2][curCol2] = 1;
                        list2.add(0, m[curRow2][curCol2]);
                        curRow2--;
                    }else{
                        break;
                    }
                }
            }
            
            if(count % 2 == 0){
                int curRow1 = dr;
                int curCol1 = dc;
                int curRow2 = tr;
                int curCol2 = tc;
                while(curCol1 != tc && curCol2 != dc){
                    if(visited[curRow1][curCol1] == 0 && visited[curRow2][curCol2] == 0){
                        visited[curRow1][curCol1] = 1;
                        list1.add(m[curRow1][curCol1]);
                        curCol1--;
                        visited[curRow2][curCol2] = 1;
                        list2.add(0, m[curRow2][curCol2]);
                        curCol2++;
                    }else{
                        break;
                    }
                }
                
                while(curRow1 != tr && curRow2 != dr){
                    if(visited[curRow1][curCol1] == 0 && visited[curRow2][curCol2] == 0){
                        visited[curRow1][curCol1] = 1;
                        list1.add(m[curRow1][curCol1]);
                        curRow1--;
                        visited[curRow2][curCol2] = 1;
                        list2.add(0, m[curRow2][curCol2]);
                        curRow2++;
                    }else{
                        break;
                    }
                }
            }
            
            count++;
            tr++;
            tc++;
            dr--;
            dc--;
        }
        
        System.out.println(list1);
        System.out.println(list2);
        if(length % 2 == 0){
            for (int i = 0; i < list1.size(); i++) {
                System.out.print(list1.get(i) + " ");
            }
            for (int i = 0; i < list2.size(); i++) {
                System.out.print(list2.get(i) + " ");
            }
        }else{
            for (int i = 0; i < list1.size(); i++) {
                System.out.print(list1.get(i) + " ");
            }
            System.out.print(m[(length - 1) / 2][(length - 1) / 2] + " ");
            for (int i = 0; i < list2.size(); i++) {
                System.out.print(list2.get(i) + " ");
            }
        }
    }

}

優化以後的代碼以下:

package com.darrenchan;

import java.util.LinkedList;
import java.util.List;

/**
 * 雙蛇形打印(優化版)
 * @author Think
 *
 */

public class SheXingPrint5 {
    public static int num = 1;
    public static void main(String[] args) {
        //給出多大的數字,就構造多大的矩陣
        int length = 4;
        int[][] m = new int[length][length];
        int temp = 1;
        for (int i = 0; i < m.length; i++) {
            for (int j = 0; j < m[i].length; j++) {
                m[i][j] = temp++;
            }
        }

        int[][] visited = new int[m.length][m[0].length];//0是沒有訪問過,1是訪問過
        
        List<Integer> list1 = new LinkedList<>();
        List<Integer> list2 = new LinkedList<>();        
        
        int tr = 0;
        int tc = 0;
        int dr = m.length - 1;
        int dc = m[0].length - 1;
        
        int count = 1;
        while(tr <= dr && tc <= dc){
            
            if(count % 2 == 1){
                int curRow1 = tr;
                int curCol1 = tc;
                while(curCol1 != dc){
                    if(visited[curRow1][curCol1] == 0){
                        visited[curRow1][curCol1] = 1;
                        list1.add(m[curRow1][curCol1]);
                        visited[length - 1 - curRow1][length - 1 - curCol1] = 1;
                        list2.add(0, m[length - 1 - curRow1][length - 1 - curCol1]);
                        curCol1++;
                    }else{
                        break;
                    }
                }
                
                while(curRow1 != dr){
                    if(visited[curRow1][curCol1] == 0){
                        visited[curRow1][curCol1] = 1;
                        list1.add(m[curRow1][curCol1]);
                        visited[length - 1 - curRow1][length - 1 - curCol1] = 1;
                        list2.add(0, m[length - 1 - curRow1][length - 1 - curCol1]);
                        curRow1++;
                    }else{
                        break;
                    }
                }
            }
            
            if(count % 2 == 0){
                int curRow1 = dr;
                int curCol1 = dc;
                while(curCol1 != tc){
                    if(visited[curRow1][curCol1] == 0){
                        visited[curRow1][curCol1] = 1;
                        list1.add(m[curRow1][curCol1]);
                        visited[length - 1 - curRow1][length - 1 - curCol1] = 1;
                        list2.add(0, m[length - 1 - curRow1][length - 1 - curCol1]);
                        curCol1--;
                    }else{
                        break;
                    }
                }
                
                while(curRow1 != tr){
                    if(visited[curRow1][curCol1] == 0){
                        visited[curRow1][curCol1] = 1;
                        list1.add(m[curRow1][curCol1]);
                        visited[length - 1 - curRow1][length - 1 - curCol1] = 1;
                        list2.add(0, m[length - 1 - curRow1][length - 1 - curCol1]);
                        curRow1--;
                    }else{
                        break;
                    }
                }
            }
            
            count++;
            tr++;
            tc++;
            dr--;
            dc--;
        }
        
        /**
         * 打印
         */
        System.out.println(list1);
        System.out.println(list2);
        if(length % 2 == 0){
            for (int i = 0; i < list1.size(); i++) {
                System.out.print(list1.get(i) + " ");
            }
            for (int i = 0; i < list2.size(); i++) {
                System.out.print(list2.get(i) + " ");
            }
        }else{
            for (int i = 0; i < list1.size(); i++) {
                System.out.print(list1.get(i) + " ");
            }
            System.out.print(m[(length - 1) / 2][(length - 1) / 2] + " ");
            for (int i = 0; i < list2.size(); i++) {
                System.out.print(list2.get(i) + " ");
            }
        }
    }

}
相關文章
相關標籤/搜索