LeetCode 有序矩阵中的搜索问题

103 阅读3分钟

在准备Amazon Virtual Interview 中,遇到了这么一道面试题

给你一个 m * n 的矩阵 grid,矩阵中的元素无论是按行还是按列,都以非递增顺序排列。 请你统计并返回 grid 中 负数 的数目。

实际上,它是来自LeetCode中的原题: 1351. 统计有序矩阵中的负数

这是属于有序矩阵中的搜索问题 这一大类问题。在这里我们学习一下此题解法(思路来自于连接)感谢原作者。

1351. 统计有序矩阵中的负数

这道原题在面试中被要求用O(n)的时间复杂度内做出来。如果加上这个要求,反而比下面几个medium的题更难。

解题思路:阶梯查找【时间复杂度O(m+n)】

  • 思路:如果在每一行的正负数之间画一个分割竖线,连接起来就是一个自左下到右上的阶梯,如下图:

    [4,3,2,|-1]

    [3,2,1,|-1]

    [1,1,|-1,-2]

    [|-1,-1,-2,-3]

  • 一次遍历:从右上到左下按照行遍历(左下到右上也可),起始位置(0,n)

    • 在每一行,j一直向左遍历,直到j-1小于0越界 或者 grid[i][j-1] > 0, 那么这一行从 grid[i][j]到grid[i][n-1]都是负数,我们可以得出负数个数为 n - j,累加到负数总数目。
    • 然后开始迭代下一行,i++, 下一行从grid[i][j]继续向左遍历。直到行i==m越界
  • 时间复杂度分析:遍历的次数就如上图的阶梯,竖着的阶梯m个,横着的n个,加起来O(m+n)

class Solution {
public:
    int countNegatives(vector<vector<int>>& grid) {
        int count = 0;
        //find the little box that is exactly next to the first negative ans;
        for(int i = 0, j = grid[0].size()-1; i < grid.size(); i++){
            while(j>=0 && grid[i][j] < 0) j--;
            count += grid[0].size() - j -1;
        }
        return count;
    }
};

自己根据这个思路自己写的解。非常有意思的解。要注意具体那根线是怎么移动的,在while区怎么复盘,很重要。 原思路题解来自LeetCode解题区

74. 搜索二维矩阵

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
       //searching: worst case: O(mn), go through each small block and find that one
       //Since it is sorted and the last one in the first row smaller than the first one in the second row
       //we can use divide and conquer: O(logn); treat it as a line
       //we can also use steps to conqure it O(m+n)
       int i = 0, j = matrix[0].size() - 1;
       while(i < matrix.size() && j >= 0){
          if(target == matrix[i][j]) return true;
          else if(target < matrix[i][j]) j--;
          else if(target > matrix[i][j]) i++;
       }
       return false;
    }
};
//Time Complexity: O(m+n) Space Complexity: O(1)

相同思路,反而更简单。 最好再用二分法再做一遍

240. 搜索二维矩阵 II

这道题算是上面题的加强版,因为上一行的最后一个数字不再小于本行的第一个数字,因此不能再用二分查找法做,只能用阶梯法解决。

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