Leetcode: 240. Search a 2D Matrix II (week2 --- medium)

 题目

题意

题解

最简单(实现最简单)的方法  复杂度:O()

找特殊位置元素法  复杂度:O(n+m)

归并方法 

总结


 题目

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.

题意

这是一个比较特别的矩阵,这个矩阵满足以下两个条件:从左到右是有序的,从上到下也是有序的。而这一道题是为了判断某个元素是否存在于这一个矩阵中。

题解

最简单(实现最简单)的方法  复杂度:O(n*m)

也就是遍历了。本来没有想过这种方法可以过检测的,结果试了一下居然是Accept。因为Vector实际上跟数组是非常相像的,所以在进行遍历的时候是可以进行下标访问的。当然啦,也是可以使用vector的find函数进行查询,find函数是优化过的,所以运行的时间会更加短。

简单的遍历算法(1384ms)

for(int i = 0; i < matrix.size(); i++){
    for(int j = 0; j < matrix[0].size(); j++){
        if(matrix[i][j] == target)
        {
            return true;
        }
    }
}
return false;

使用了find算法函数之后,(628 ms),不知道这个函数的算法实现是怎么写的,但是看C++ -- Reference网站的时候,里面只是提到了跟前面的实现是等同的。

for(int i = 0; i < matrix.size(); i++){
    vector<int>::iterator j = find(matrix[i].begin(), matrix[i].end(), target);
    if(j != matrix[i].end()){
        return true;
    }
}
return false;

找特殊位置元素法  复杂度:O(n+m)

这一道题的好处在于元素从左到右以及从上到下都是有序的。

而坏处也同样在于在每一个节点大于该节点的方向存在两个,所以就不好进行决策。但是我们可以发现在下边界以及有边界上的点的特性确实比较好的,因为大于该元素的方向只有一个,而小于该元素的方向则可以依据一定的规则而变为一个,这里是采用第一行的最后的元素作为最开始的起点,然后根据该点值与目标值之间的大小关系,当目标值大于该元素的时候便进行纵坐标的下移操作。相反则进行横坐标的左移操作。这样的话,算法的复杂度便会下降很多,也就是则坏的情况下复杂度为O(m+n)

一下方法的时间消耗为:36ms

int m = matrix.size();
if(m == 0){
    return false;
}
int n = matrix[0].size();
int i = 0;
int j = n - 1;
while(i < m && j >= 0){
    if(matrix[i][j] == target){
        return true;
    }
    else if(matrix[i][j] < target ){
        i++;
    }
    else{
        j--;
    }
}
return false;

归并方法 

以下方法的时间是200ms,比起前面的找特殊元素的算法时间消耗也是比较大的了。主要的步骤在与每次对行和列进行二分操作,那么久会分成四个部分,然后在跟据这四个部分的首位元素进行大小的比较然后判断这个元素是否存在与这个矩阵之中。

bool divide(vector<vector<int>>& matrix, int target, int row1, int col1, int row2, int col2){
    if(row1 > row2 || col1 > col2){
        return false;
    }
    else if(row1 == row2 && col1 == col2){
        return matrix[row1][col1] == target;
    }
    else if(target < matrix[row1][col1] || target > matrix[row2][col2]){
        return false;
    }
    int row_mid = row1 + (row2 - row1)/2;
    int col_mid = col1 + (col2 - col1)/2;
    return (
            divide(matrix, target, row1, col1, row_mid, col_mid) ||
            divide(matrix, target, row1, col_mid + 1, row_mid, col2) ||
            divide(matrix, target, row_mid + 1, col1, row2, col_mid) ||
            divide(matrix, target, row_mid + 1, col_mid, row2, col2)
            );
}
bool searchMatrix(vector<vector<int>>& matrix, int target) {
    if(matrix.size() == 0 || matrix[0].size() == 0){
        return false;
    }
    return divide(matrix, target, 0, 0, matrix.size() - 1, matrix[0].size()- 1);
}

总结

上面总共提供了三种方法,但是还是有其他优化方法的,比如:由于每一行每一列是有序的,所以可以利用查找算法进行复杂度的优化,可以利用二分查找等。这道题还提示了我们以后再做题的时候可以进行一番观察之后找到特殊的位置的元素然后进行突破。

猜你喜欢

转载自blog.csdn.net/qq_36347365/article/details/82667364
今日推荐