题目描述
给你一个 m * n
的矩阵 grid
,矩阵中的元素无论是按行还是按列,都以非递增顺序排列。
请你统计并返回 grid
中 负数 的数目。
样例
输入:grid = [[4,3,2,-1],[3,2,1,-1],[1,1,-1,-2],[-1,-1,-2,-3]]
输出:8
解释:矩阵中共有 8 个负数。
输入:grid = [[3,2],[1,0]]
输出:0
输入:grid = [[1,-1],[-1,-1]]
输出:3
输入:grid = [[-1]]
输出:1
限制
m == grid.length
n == grid[i].length
1 <= m, n <= 100
-100 <= grid[i][j] <= 100
算法
(单调性) $O(m + n)$
- 从矩阵的右上角开始出发,令
i = 0, j = n - 1
。 - 对于每一行,如果
j >= 0 && grid[i][j] < 0
,则j
向前移动,在这一行中答案累加n - 1 - y
,继续下一行。 - 这里利用了矩阵行和列都是非增的单调性的性质,从右上角出发,一个方向是增加的,一个方向是下降的,所以在每行找到第一个大于等于 0 的列,根据单调性,后续行所有大于等于这一列的数字都是负的。
时间复杂度
- 对于每个
i
,j
都是单调不增的,所以时间复杂度为 $O(m + n)$。
空间复杂度
- 仅需要常数的额外空间。
C++ 代码
class Solution {
public:
int countNegatives(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size();
int ans = 0;
for (int i = 0, j = n - 1; i < m; i++) {
while (j >= 0 && grid[i][j] < 0)
j--;
ans += n - 1 - j;
}
return ans;
}
};