1. 程式人生 > >LintCode-28. 搜尋二維矩陣

LintCode-28. 搜尋二維矩陣

題目描述

寫出一個高效的演算法來搜尋 m × n矩陣中的值。
這個矩陣具有以下特性:
每行中的整數從左到右是排序的。
每行的第一個數大於上一行的最後一個整數。
樣例
考慮下列矩陣:
[
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
給出 target = 3,返回 true
挑戰
O(log(n) + log(m)) 時間複雜度

分析

因為是有序的,所以直接看每個小列表的最後一個是不是小於這個數就知道在不在這個小列表裡了。

程式碼

class Solution {
public:
    /*
     * @param matrix: matrix, a list of lists of integers
     * @param target: An integer
     * @return: a boolean, indicate whether matrix contains target
     */
    bool searchMatrix(vector<vector<int>> &matrix, int target) {
        // write your code here
for(vector<int> i : matrix) { if(i.back() >= target) { for(int j : i) { if(j == target) return true; } } } return false; } };

優化

根據挑戰的提示:時間複雜度為O(log(n) + log(m)),即O(logMN)。再根據題目中所說的行列均有序可以發現使用兩次二分法查詢並且沒有重複元素。不過需要注意外層二分法條件與正常不同,程式碼如下:

class Solution {
public:
    /*
     * @param matrix: matrix, a list of lists of integers
     * @param target: An integer
     * @return: a boolean, indicate whether matrix contains target
     */
    bool searchMatrix(vector<vector<int>> &matrix, int target) {
        // write your code here
        int nlow = 0, nhigh = matrix.size() - 1;
        while(nlow <= nhigh) {
            int nmid = nlow + (nhigh - nlow) / 2;
            if(matrix[nmid][matrix[nmid].size() - 1] < target) {
                nlow = nmid + 1;
            } else if(matrix[nmid][0] > target) {
                nhigh = nmid - 1;
            } else {
                int mlow = 0, mhigh = matrix[nmid].size() - 1;
                while(mlow <= mhigh) {
                    int mmid = mlow + (mhigh - mlow) / 2;
                    if(matrix[nmid][mmid] < target) {
                        mlow = mmid + 1;
                    } else if(matrix[nmid][mmid] > target) {
                        mhigh = mmid - 1;
                    } else {
                        return true;
                    }
                }
                return false;
            }
        }
        return false;
    }
};

總結

二分法時間複雜度為O(logN).