每日一題——搜索二維矩陣

菜雞每日一題系列打卡74

每天一道算法題目 

小夥伴們一起留言打卡

堅持就是勝利,我們一起努力!

題目描述(引自LeetCode)

編寫一個高效的算法來判斷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

題目分析

這明顯是一道二分法的題目。我們可以採用兩種思路來實現:一種是先對行進行二分,找到target可能在的行,然後再對列進行二分,判斷target是否存在。另一種是對所有的數當作一維有序數組進行二分,然後映射到二維數組的對應座標中。

Talk is cheap,菜雞將採用上述兩種方法進行實現。話不多說,上代碼!

代碼實現

class Solution {


    public boolean searchMatrix(int[][] matrix, int target) {
        // 特殊情況處理
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false;


        int rowStart = 0, rowEnd = matrix.length - 1, rowMid = 0;
        int colStart = 0, colEnd = matrix[0].length - 1;


        // 二分法尋找行
        while (rowStart <= rowEnd) {
            rowMid = rowStart + ((rowEnd - rowStart) >> 1);
            if (matrix[rowMid][0] == target) return true;
            else if (matrix[rowMid][0] > target) rowEnd = rowMid - 1;
            else if (matrix[rowMid][colEnd] < target) rowStart = rowMid + 1;
            else break;
        }


        // 二分法尋找列
        while (colStart <= colEnd) {
            int colMid = colStart + ((colEnd - colStart) >> 1);
            if (matrix[rowMid][colMid] == target) return true;
            else if (matrix[rowMid][colMid] > target) colEnd = colMid - 1;
            else colStart = colMid + 1;
        }


        return false;
    }


}
class Solution {


    public boolean searchMatrix(int[][] matrix, int target) {
        // 特殊情況處理
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false;


        int m = matrix.length;
        int n = matrix[0].length;


        // 二分法
        int start = 0, end = m * n - 1;
        while (start <= end) {
            // 按照一維數組來計算中間座標
            int mid = start + ((end - start) >> 1);
            // 定位中間座標所在行
            int row = mid / n;
            // 定位中間座標所在列
            int column = mid % n;
            // 比較判斷
            if (matrix[row][column] == target) return true;
            else if (matrix[row][column] > target) end = mid - 1;
            else start = mid + 1;
        }
        return false;
    }


}

代碼分析

對代碼進行分析,第一種實現方式,對行和列分別進行二分,時間複雜度爲O(max(logm, logn)),空間複雜度爲O(1);第二種實現方式,對所有數字進行二分,然後映射到具體的二維數組座標,時間複雜度爲O(log(mn)),空間複雜度爲O(1)。

乍一看,覺得第一種實現方式的時間複雜度好像更低一些,其實只要稍加分析,對於第二種實現方式,log(mn) = logm + logn,就會發現,這只是個數學遊戲而已,兩種實現方式的時間複雜度並無本質區別。

執行結果

對行和列分別進行二分的執行結果

對所有數字進行二分然後進行下標映射的執行結果

學習 | 工作 | 分享

????長按關注“有理想的菜雞

只有你想不到,沒有你學不到

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章