[LeetCode] 74. Search a 2D Matrix 搜索一個二維矩陣

 

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:html

  • Integers in each row are sorted from left to right.
  • The first integer of each row is greater than the last integer of the previous row.

Example 1:git

Input:
matrix = [
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]
target = 3
Output: true

Example 2:github

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

 

這道題要求搜索一個二維矩陣,因爲給的矩陣是有序的,因此很天然的想到要用二分查找法,能夠在第一列上先用一次二分查找法找到目標值所在的行的位置,而後在該行上再用一次二分查找法來找是否存在目標值。對於第一個二分查找,因爲第一列的數中可能沒有 target 值,該如何查找呢,是博主以前的總結帖 LeetCode Binary Search Summary 二分搜索法小結 中的哪一類呢?若是是查找第一個不小於目標值的數,當 target 在第一列時,會返回 target 所在的行,但若 target 不在的話,有可能會返回下一行,很差統一。因此能夠查找第一個大於目標值的數,也就是總結帖中的第三類,這樣只要回退一個,就必定是 target 所在的行。但須要注意的一點是,若是返回的是0,就不能回退了,以避免越界,記得要判斷一下。找到了 target 所在的行數,就能夠再次使用二分搜索,此時就是總結帖中的第一類了,查找和 target 值相同的數,也是最簡單的一類,分分鐘搞定便可,參見代碼以下:數組

 

解法一:post

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        if (matrix.empty() || matrix[0].empty()) return false;
        int left = 0, right = matrix.size();
        while (left < right) {
            int mid = (left + right) / 2;
            if (matrix[mid][0] == target) return true;
            if (matrix[mid][0] <= target) left = mid + 1;
            else right = mid;
        }
        int tmp = (right > 0) ? (right - 1) : right;
        left = 0;
        right = matrix[tmp].size();
        while (left < right) {
            int mid = (left + right) / 2;
            if (matrix[tmp][mid] == target) return true;
            if (matrix[tmp][mid] < target) left = mid + 1;
            else right = mid;
        }
        return false;
    }
};

 

固然這道題也可使用一次二分查找法,若是咱們按S型遍歷該二維數組,能夠獲得一個有序的一維數組,只須要用一次二分查找法,而關鍵就在於座標的轉換,如何把二維座標和一維座標轉換是關鍵點,把一個長度爲n的一維數組轉化爲 m*n 的二維數組 (m*n = n)後,那麼原一維數組中下標爲i的元素將出如今二維數組中的 [i/n][i%n] 的位置,有了這一點,代碼很好寫出來了:url

 

解法二:spa

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        if (matrix.empty() || matrix[0].empty()) return false;
        int m = matrix.size(), n = matrix[0].size();
        int left = 0, right = m * n;
        while (left < right) {
            int mid = (left + right) / 2;
            if (matrix[mid / n][mid % n] == target) return true;
            if (matrix[mid / n][mid % n] < target) left = mid + 1;
            else right = mid;
        }
        return false;
    }
};

 

這道題其實也能夠不用二分搜索法,直接使用雙指針也是能夠的,i指向0,j指向列數,這樣第一個被驗證的數就是二維數組右上角的數字,假如這個數字等於 target,直接返回 true;若大於 target,說明要減少數字,則列數j自減1;若小於 target,說明要增長數字,行數i自增1。若 while 循環退出了仍是沒找到 target,直接返回 false 便可,參見代碼以下:指針

 

解法三:code

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        if (matrix.empty() || matrix[0].empty()) return false;
        int i = 0, j = (int)matrix[0].size() - 1;
        while (i < matrix.size() && j >= 0) {
            if (matrix[i][j] == target) return true;
            else if (matrix[i][j] > target) --j;
            else ++i;
        }   
        return false;
    }
};

 

Github 同步地址:htm

https://github.com/grandyang/leetcode/issues/74

 

相似題目:

Search a 2D Matrix II

 

參考資料:

https://leetcode.com/problems/search-a-2d-matrix/

https://leetcode.com/problems/search-a-2d-matrix/discuss/26292/Java-clear-solution

https://leetcode.com/problems/search-a-2d-matrix/discuss/26220/Don't-treat-it-as-a-2D-matrix-just-treat-it-as-a-sorted-list

 

LeetCode All in One 題目講解彙總(持續更新中...)

相關文章
相關標籤/搜索