矩陣問題

1、轉圈打印矩陣

【題目】函數

  給定一個整型矩陣matrix,請按照轉圈的方式打印它。例如:spa

  

  打印結果爲:1,2,3,4,8,12,16,15,14,13,9,5,6,7,11, 103d

  

  要求:額外空間複雜度爲O(1)。code

【分析】blog

  用4個變量來標記左上角的點和右下角的點。class

  若是要打印這2個點造成矩陣的邊界,能夠寫一個函數,具體是:col1++,加到col2的位置中止,而後row1++,加到row2的位置中止;而後row2--,減到row1停;col2--,減到col1中止變量

              

  打印完最外層的1圈後,左上角的點往右下方移動,右下角的點往左上方移動;當row1>row2或col1>col2時流程結束遍歷

      

【代碼實現】im

public class PrintMatrixSpiralOrder {

    public static void spiralOrderPrint(int[][] matrix) {
        int row1 = 0;
        int col1 = 0;
        int row2 = matrix.length - 1;
        int col2 = matrix[0].length - 1;
        while (row1 <= row2 && col1 <= col2) {
            printEdge(matrix, row1++, col1++, row2--, col2--);
        }
    }

    public static void printEdge(int[][] m, int row1, int col1, int row2, int col2) {
        //若是這個矩陣只有1行數
        if (row1 == row2) {
            //打印這一行
            for (int i = col1; i <= col2; i++) {
                System.out.print(m[i][col1] + " ");
            }
            //若是這個矩陣只有1列
        } else if (col1 == col2) {
            //打印這一列
            for (int i = row1; i <= row2; i++) {
                System.out.print(m[i][col1] + " ");
            }
            //若是是多乘多的矩陣
        } else {
            int curC = col1;
            int curR = row1;
            while (curC != col2) {
                System.out.print(m[row1][curC] + " ");
                curC++;
            }
            while (curR != row2) {
                System.out.print(m[curR][col2] + " ");
                curR++;
            }
            while (curC != col1) {
                System.out.print(m[row2][curC] + " ");
                curC--;
            }
            while (curR != row1) {
                System.out.print(m[curR][col1] + " ");
                curR--;
            }
        }
    }

    public static void main(String[] args) {
        int[][] matrix = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12},
                {13, 14, 15, 16}};
        spiralOrderPrint(matrix);
    }
}

 

2、旋轉正方形矩陣

【題目】總結

  給定一個整型正方形矩陣matrix,請把該矩陣調整成順時針旋轉90度的樣子。
  要求: 額外空間複雜度爲O(1)。

【分析】

  在給定的正方形中,先轉最外圈,再轉裏面的。若是能保證最外層的數能轉對,裏面再依次轉完便可。
  舉個例子:

  

  若是能把最外1圈的數轉對,再轉裏面1圈(6,7,10,11),那麼總體就旋轉成功了。
  先看最外1圈,從1開始,一、四、1六、13之間相互交換位置,即1→4,4→16,16→13,13→1。
  而後從2開始,二、八、1五、9之間交換位置。再看第三組,三、十二、1四、5之間交換位置。

【代碼實現】

public class RotateMatrix {
    public static void rotate(int[][] matrix) {
        int row1 = 0;
        int col1 = 0;
        int row2 = matrix.length - 1;
        int col2 = matrix[0].length - 1;
        while (row1 < row2) {
            rotateEdge(matrix, row1++, col1++, row2--, col2--);
        }
    }

    /**
     * 左上角的(row1,col1)和右下角的(row2,col2)必定要組成一個正方形,這是調用此函數的前提
     *
     * @param m
     * @param row1 左上角的行號
     * @param col1 左上角的列號
     * @param row2 右下角的行
     * @param col2 右下角的列
     */
    public static void rotateEdge(int[][] m, int row1, int col1, int row2, int col2) {
        int times = col2 - col1;
        int tmp = 0;
        //從1出發,一、四、1六、13之間相互交換位置,直至
        for (int i = 0; i < times; i++) {
            tmp = m[row1][col1 + i];
            m[row1][col1 + i] = m[row2 - i][col1];
            m[row2 - i][col1] = m[row2][col2 - i];
            m[row2][col2 - i] = m[row1 + i][col2];
            m[row1 + i][col2] = tmp;
        }
    }

    public static void printMatrix(int[][] matrix) {
        for (int i = 0; i != matrix.length; i++) {
            for (int j = 0; j != matrix[0].length; j++) {
                System.out.print(matrix[i][j] + " ");
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 },
                { 13, 14, 15, 16 } };
        printMatrix(matrix);
        rotate(matrix);
        System.out.println("=========");
        printMatrix(matrix);
    }
}

3、「之」字形打印矩陣

【題目】

  給定一個矩陣matrix,按照「之」字形的方式打印這個矩陣,例如: 1 2 3 4 5 6 7 8 9 10 11 12

  

  「之」字形打印的結果爲:1,2,5,9,6,3,4,7,10,11,8,12
  要求:額外空間複雜度爲O(1)。

【分析】

  若是把思路限制在1怎麼變到2,2怎麼變到5,5怎麼變到9。。。這樣是很愚蠢的!

  咱們應該這樣想:

  有一個(row1,col1),記爲a點、(row2,col2),記爲b點,一開始指向1的位置,並打印它。每次打印完後,a向右移動,移動到最右邊後向下移動;b先向下移動,到最下方後再往右移動。

  當a移動到2,b移動到5時,a、b兩點可造成1條對角線;當a移動到3,b移動到9時,兩點間也能夠造成一條對角線;a移動到4,b移動到10時,又是1條對角線。。。

                   

【代碼實現】

public class ZigZagPrintMatrix {

    public static void printMatrixZigZag(int[][] matrix) {
        int row1 = 0;
        int col1 = 0;
        int row2 = 0;
        int col2 = 0;
        int endR = matrix.length - 1;
        int endC = matrix[0].length - 1;
        boolean fromUp = false;
        //當row1沒走到結尾
        while (row1 != endR + 1) {
            printLevel(matrix, row1, col1, row2, col2, fromUp);
            //到col1觸到最後1列時,row1纔開始增長
            row1 = col1 == endC ? row1 + 1 : row1;
            //若是col1已經到最後,就不變,不然col1增長
            col1 = col1 == endC ? col1 : col1 + 1;
            col2 = row2 == endR ? col2 + 1 : col2;
            row2 = row2 == endR ? row2 : row2 + 1;
            //對角線交替着打印
            fromUp = !fromUp;
        }
        System.out.println();
    }

    /**
     * (row1,col1)和(row2,col2)兩個點連起來必定是一條對角線,這個函數就是打印對角線上的元素
     * 而且這個函數能夠實現從左下方到右上方打印,也能夠實現從右上方到左下方的打印
     * @param m
     * @param row1
     * @param col1
     * @param row2
     * @param col2
     * @param fromUp 控制對角線打印的方向。true:右上方到左下方   false:左下方到右上方
     */
    public static void printLevel(int[][] m, int row1, int col1, int row2, int col2, boolean fromUp) {
        //fromUp爲true時,從右上方到左下方依次打印對角線上的元素
        if (fromUp) {
            //row1 != row2 + 1等價於row1<=row2
            while (row1 != row2 + 1) {
                System.out.print(m[row1++][col1--] + " ");
            }
            //fromUp爲false時,從左下方到右上方依次打印對角線上的元素
        } else {
            while (row2 != row1 - 1) {
                System.out.print(m[row2--][col2++] + " ");
            }
        }
    }

    public static void main(String[] args) {
        int[][] matrix = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
        printMatrixZigZag(matrix);
    }
}

4、在行列都排好序的矩陣中找數

【題目】

  給定一個有N*M的整型矩陣matrix和一個整數K,matrix的每一行和每一 列都是排好序的。實現一個函數,判斷K是否在matrix中。 例如:

  

  若是K爲7,返回true;若是K爲6,返回false。
  要求:時間複雜度爲O(N+M),額外空間複雜度爲O(1)。

 

【分析】

  若是經過遍歷的方式,一共N*M個數,每一個數都遍歷,時間複雜度就是O(N*M),顯然不符合要求。

  經過例子來分析這個題目:

  

  若是要判斷6是否在上面的矩陣中,能夠從右上角9開始查,9>6,由於每一列都是有序的,因此9這列底下的數必定沒有6;

  

  而後從9向左移動,來到7的位置,7>6,因此7底下的數必定沒有6

  

  繼續從7往左移動,來到5的位置,5<6,因此5的左邊必定比6小,因而從5往下走,來到6的位置,返回true

  

  總結就是:從右上角開始,當前數大於要找的數,向左移動;當前數小於要找的數,向下移動;當前數若是等於要找的數,返回true;若是走到越界的位置還沒找到,必定不存在,返回false。

  注意:從左下角開始找也是能夠的。可是不能從左上角或右下角開始找!

【代碼實現】

public class FindNumInSortedMatrix {
    public static boolean isContains(int[][] matrix, int K) {
        int row = 0;
        int col = matrix[0].length - 1;
        while (row < matrix.length && col > -1) {
            if (matrix[row][col] == K) {
                return true;
            } else if (matrix[row][col] > K) {
                col--;
            } else {
                row++;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        int[][] matrix = new int[][]{{0, 1, 2, 3, 4, 5, 6},// 0
                {10, 12, 13, 15, 16, 17, 18},// 1
                {23, 24, 25, 26, 27, 28, 29},// 2
                {44, 45, 46, 47, 48, 49, 50},// 3
                {65, 66, 67, 68, 69, 70, 71},// 4
                {96, 97, 98, 99, 100, 111, 122},// 5
                {166, 176, 186, 187, 190, 195, 200},// 6
                {233, 243, 321, 341, 356, 370, 380} // 7
        };
        int K = 233;
        System.out.println(isContains(matrix, K));
    }
}
相關文章
相關標籤/搜索