LeetCode240. Search a 2D Matrix II题解

来源:互联网 发布:开淘宝网店进货渠道 编辑:程序博客网 时间:2024/06/05 18:01

1. 题目描述

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties: Integers in each row are sorted in ascending from left to right. Integers in each column are sorted in ascending from top to bottom.

2. 样例

For example, consider the following 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]]

Given target = 5, return true;
Given target = 20, return false.

3. 分析

拿到题目,首先理解题意:非常简单,给了一个二维的矩阵,这个矩阵具有很好的性质:每一行从左到右按照升序排列,每一列从上到下按照升序排列,给定了一个目标数,我们的任务就是要判断这个矩阵中有没有这个数。看起来很简单,思路也很简单,我在这里用以下4种方法给大家分享一下。

3.1. 直接搜索

时间复杂度O(n^2)
简单粗暴,能直接想到的思路:二维数组的每一行是一个一维数组,对每个一维数组进行最普通的遍历寻找。也就是说,直接两层循环嵌套,时间复杂度O(n^2)。我的代码执行结果如下:用了569ms跑完了所有的测试样例。
这里写图片描述

3.2. 优化后的直接搜索

时间复杂度O(n^2)
由于原来的数组具有很好的性质:即是有一定的顺序排列,那么我们用这个性质可以对代码进行优化。首先判断数组的每一维长度,如果发现每一行长度仅为1,那么我们就可以将原数组化简为一个一维数组,然后调用遍历寻找。其他情况下,我们判断目标数target是否在每一行数组之内(即大于等于最左边的元素,小于等于最右边的元素),如果在的话,才调用遍历搜索,不在的话,就跳过此行数组,节约了某些不必要的时间。我的代码执行结果如下:用了352ms跑完了所有的测试样例。
这里写图片描述

3.3. 优化后的二分搜索

时间复杂度O(nlogn)
主题的搜索部分同上,但是在搜索每一行元素的时候,将原来的直接遍历改为二分查找,由于二分查找的时间复杂度是O(logn),加上嵌套的外层循环,所以时间复杂度降为O(nlogn)。我的代码执行结果如下:用了142ms跑完了所有的测试样例。
这里写图片描述

3.4. 右上角开始的搜索

时间复杂度O(m+n)
非常巧妙的方法,充分利用了给出的矩阵性质。我们从右上角开始搜索,一旦发现当前元素等于目标元素,就是找到了。
没发现的话:如果当前元素大于目标元素,说明目标元素应该在当前元素的左上方,因为是从右上角开始,所以搜索方向只能向左继续;如果当前元素小于目标元素:说明目标元素应该在当前元素右下方,因为是从右上角开始,所以搜索方向只能向下继续,很快遍历整个矩阵。时间复杂度O(m+n),m和n分别代表矩阵的行数和列数。我的代码执行结果如下:用了102ms跑完了所有的测试样例。
这里写图片描述

4. 源码

4.1. 直接搜索

class Solution {public:    bool subSearchMatrix(vector<int>& m, int target) {        int length = m.size();        for (int i = 0; i < length; i++) {            if (m[i] == target) {                return true;            }        }        return false;    }    bool searchMatrix(vector<vector<int>>& matrix, int target) {        int length = matrix.size();        for (int i = 0; i < length; i++) {            bool result = subSearchMatrix(matrix[i], target);            if (result == true) {                return true;            }        }        return false;    }};

4.2. 优化后的直接搜索

class Solution {public:    bool subSearchMatrix(vector<int>& m, int target) {        int length = m.size();        for (int i = 0; i < length; i++) {            if (m[i] == target) {                return true;            }        }        return false;    }    bool searchMatrix(vector<vector<int>>& matrix, int target) {        int length_col = matrix.size();        bool result;        if (length_col == 0) {            return false;        }        int length_row = matrix[0].size();        if (length_row == 0) {            return false;        }        if (length_row == 1){            for (int i = 0; i < length_col; i++) {                matrix[0].push_back(matrix[i][0]);            }            result = subSearchMatrix(matrix[0], target);            return result;        }        else {            int i;            for (i = 0; i < length_col; i++) {                if (matrix[i][0] <= target && matrix[i][length_row-1] >= target) {                    result = subSearchMatrix(matrix[i], target);                    if (result == true) {                        return true;                    }                };            }        }        return false;    }};

4.3. 优化后的二分搜索

class Solution {public:    bool subSearchMatrix(vector<int>& m, int target) {        int left, right, mid;        left = 0, right = m.size()-1;        while(left <= right) {            mid = (left + right) / 2;            if (m[mid] == target) {                return true;            }            else if (m[mid] > target) {                right = mid - 1;            }            else {                left = mid + 1;            }        }        return false;    }    bool searchMatrix(vector<vector<int>>& matrix, int target) {        int length = matrix.size();        for (int i = 0; i < length; i++) {            bool result = subSearchMatrix(matrix[i], target);            if (result == true) {                return true;            }        }        return false;    }};

4.4. 右上角开始的搜索

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

5. 心得

本题虽然不难,但是学到了比较多的东西。一道题可有很多种方法去解,往往最容易想到的方法是耗时最长的算法。

0 0