算法-矩陣遍歷問題專輯

1、螺旋矩陣

54. 螺旋矩陣

給定一個包含 m x n 個元素的矩陣(m 行, n 列),請按照順時針螺旋順序,返回矩陣中的所有元素。

示例 1:

輸入:
[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]
輸出: [1,2,3,6,9,8,7,4,5]
示例 2:

輸入:
[
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12]
]
輸出: [1,2,3,4,8,12,11,10,9,5,6,7]

這個題目其實很簡單,解決的關鍵在於怎麼確定遍歷的邊界條件。

把矩陣看成一個洋蔥,我們一層一層的撥開矩陣的心。也就是矩陣的層。
定義兩個變量:當前層layer、剩餘未打印元素數量count作爲邊界條件

我們再按照從左到右,東上到下,從右到左,從下到上四個方向遍歷一遍,即爲完成層數條件,每次打印的時候都減去一個元素,當元素減到0了,也就結束了遍歷

    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> list=new ArrayList<>();
        if(matrix.length==0){
            return list;
        }
        int m=matrix.length-1;
        int n=matrix[0].length-1;
        int count=(m+1)*(n+1);
        int layer=0;
        while (count>0){
            //從左到右
            for (int i=layer;i<=n-layer&&count>0;i++){
                list.add(matrix[layer][i]);
                count--;
            }
            //從上到下
            for (int i=layer+1;i<=m-layer&&count>0;i++){
                list.add(matrix[i][n-layer]);
                count--;
            }
            //從右到左
            for (int i=n-layer-1;i>=layer&&count>0;i--){
                list.add(matrix[m-layer][i]);
                count--;
            }
            //從下到上
            for (int i=m-layer-1;i>layer&&count>0;i--){
                list.add(matrix[i][layer]);
                count--;
            }
            layer++;//讀完一層,繼續下一層
        }
        return list;
    }

2、旋轉圖像

先看一下題目描述:

48. 旋轉圖像

給定一個 n × n 的二維矩陣表示一個圖像。

將圖像順時針旋轉 90 度。

說明:

你必須在原地旋轉圖像,這意味着你需要直接修改輸入的二維矩陣。請不要使用另一個矩陣來旋轉圖像。

示例 1:

給定 matrix = 
[
  [1,2,3],
  [4,5,6],
  [7,8,9]
],

原地旋轉輸入矩陣,使其變爲:
[
  [7,4,1],
  [8,5,2],
  [9,6,3]
]
示例 2:

給定 matrix =
[
  [ 5, 1, 9,11],
  [ 2, 4, 8,10],
  [13, 3, 6, 7],
  [15,14,12,16]
], 

原地旋轉輸入矩陣,使其變爲:
[
  [15,13, 2, 5],
  [14, 3, 4, 1],
  [12, 6, 8, 9],
  [16, 7,10,11]
]

感覺這題更像是一個數學題,對於本題,有兩種解決方案。

第一種:按順時針讀取元素到一個數組裏,然後調整數組元素填充到裏面去
第二種:取矩陣的轉置,然後按行反轉

第一種寫法較爲繁瑣,這裏給出第二種寫法

    public void rotate(int[][] matrix) {
        int n=matrix.length;
        //矩陣轉置
        for(int i=0;i<n;i++){
            for(int j=0;j<=i;j++){
                int temp=matrix[i][j];
                matrix[i][j]=matrix[j][i];
                matrix[j][i]=temp;
            }
        }
        //按行反轉
        for(int i=0;i<n;i++){
            int left=0,right=n-1;
            while(left<right){
                int temp=matrix[i][left];
                matrix[i][left]=matrix[i][right];
                matrix[i][right]=temp;
                left++;
                right--;
            }
        }
    }

3、搜索二維矩陣 II

240. 搜索二維矩陣 II

編寫一個高效的算法來搜索 m x n 矩陣 matrix 中的一個目標值 target。該矩陣具有以下特性:

每行的元素從左到右升序排列。
每列的元素從上到下升序排列。
示例:

現有矩陣 matrix 如下:

[
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
]
給定 target = 5,返回 true。

給定 target = 20,返回 false。

這個題目的解法有點巧妙,本質上是剪枝法。從右上角開始搜,右上角的值與目標值對比,每次裁剪一行或者一列,複雜度O(m+n)

    public boolean searchMatrix(int[][] matrix, int target) {
        if(matrix.length==0){
            return false;
        }
        int right=matrix[0].length-1,top=0;//右上角
        while(right>=0&&top<matrix.length){
            if(matrix[top][right]>target){
                right--;//裁掉一列
            }else if(matrix[top][right]<target){
                top++;//裁掉一行
            }else{
                return true;
            }
        }
        return false;
    }

4、搜索二維矩陣

74. 搜索二維矩陣

編寫一個高效的算法來判斷 m x n 矩陣中,是否存在一個目標值。該矩陣具有如下特性:

每行中的整數從左到右按升序排列。
每行的第一個整數大於前一行的最後一個整數。
示例 1:

輸入:
matrix = [
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]
target = 3
輸出: true
示例 2:

輸入:
matrix = [
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]
target = 13
輸出: false

這倆題是一樣的,直接套上就行了

    public boolean searchMatrix(int[][] matrix, int target) {
        if(matrix.length==0){
            return false;
        }
        int right=matrix[0].length-1,top=0;//右上角
        while(right>=0&&top<matrix.length){
            if(matrix[top][right]>target){
                right--;//裁掉一列
            }else if(matrix[top][right]<target){
                top++;//裁掉一行
            }else{
                return true;
            }
        }
        return false;
    }

效率也不賴

執行結果:
通過
顯示詳情
執行用時 :
0 ms
, 在所有 Java 提交中擊敗了
100.00%
的用戶
內存消耗 :
39.3 MB
, 在所有 Java 提交中擊敗了
94.29%
的用戶
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章