题目描述
给你一个 m * n 的矩阵 grid,矩阵中的元素无论是按行还是按列,都以非递增顺序排列。 请你统计并返回 grid 中 负数 的数目。
示例1:
输入: grid = [[4,3,2,-1],[3,2,1,-1],[1,1,-1,-2],[-1,-1,-2,-3]]
输出: 8
解释: 矩阵中共有 8 个负数。
示例2:
输入: grid = [[3,2],[1,0]]
输出: 0
提示
- m == grid.length
- n == grid[i].length
- 1 <= m, n <= 100
- -100 <= grid[i][j] <= 100
方法一:暴力
解题思路
一个个遍历矩阵的所有数字,统计所有负数。
代码
class Solution {
public:
int countNegatives(vector<vector<int>>& grid) {
int ans = 0;
for(auto x: grid)
for(auto y: x)
if(y < 0)
ans++;
return ans;
}
};
复杂度分析
- 时间复杂度:O(nm)。
- 空间复杂度:O(1)。
方法二:二分查找
解题思路
矩阵中的元素无论是按行还是按列,都以非递增顺序排列,所以可以利用二分查找来找到每行中的第一个负数,从这个位置到末尾便是每行中负数的个数,最后累计起来。
代码
class Solution {
public:
int countNegatives(vector<vector<int>>& grid) {
int ans = 0;
int m = grid.size();
int n = grid[0].size();
for(int i = 0; i < m; i++)
{
int l = 0, r = n - 1, mid;
while(l < r)
{
mid = l + (r - l) / 2;
if(grid[i][mid] < 0) r = mid;
else l = mid + 1;
}
if(grid[i][l] < 0) ans += n - l;
}
return ans;
}
};
复杂度分析
- 时间复杂度:O( n l o g m nlogm nlogm)。
- 空间复杂度:O(1)。
方法三:倒序遍历
解题思路
整个矩阵是每行每列均非递增,说明了每一行从前往后第一个负数的位置是不断递减的。
考虑我们已经算出第 i 行的从前往后第一个负数的位置
p
o
s
i
pos_i
posi ,那么第 i+1 行的时候,
p
o
s
i
+
1
pos_{i + 1}
posi+1 的位置肯定是位于
[
0
,
p
o
s
i
]
[0, pos_i]
[0,posi] 中,所以对于第 i+1 行我们倒着从
p
o
s
i
pos_i
posi循环找
p
o
s
i
+
1
pos_{i + 1}
posi+1 即可,这个循环起始变量是一直在递减的。
代码
class Solution {
public:
int countNegatives(vector<vector<int>>& grid) {
int ans = 0;
int m = grid.size(), n = grid[0].size(), pos = grid[0].size() - 1;
for(int i = 0; i < m; i++)
{
int j;
for(j = pos; j >= 0; j--)
if(grid[i][j] >= 0)
{
if(j + 1 < n)
{
pos = j + 1;
ans += n - pos;
}
break;
}
if(j == - 1)
{
ans += n;
pos = -1;
}
}
return ans;
}
};
复杂度分析
- 时间复杂度:O( n + m n + m n+m)。
- 空间复杂度:O(1)。