给你一个 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
示例 3:
输入:grid = [[1,-1],[-1,-1]]
输出:3
示例 4:
输入:grid = [[-1]]
输出:1
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 100
-100 <= grid[i][j] <= 10
解析
该题目可以分解为求一维数组中比0小的数的个数, 和“荷兰国旗”类似。但是更加简单,因为次数一维数组是有序的。
解答
暴力循环破解法
因为数组是递减排列,所以从后向前循环比较好
if (grid == null){
return 0;
}
int count = 0;
for (int i = 0; i < grid.length; i++){
int[] temp = grid[i];
for (int j = temp.length - 1; j > -1 ; j--){
if (temp[j] >= 0){
break; // 跳出上一层讯息
}else {
count++;
}
}
}
return count;
利用数组性质[更快]
根据题目规则 从右上角开始搜索:
例如二维数组:
4 3 2 -1
3 2 1 -1
1 1 -1 -2
-1 -1 -2 -3
观察可以得出规律如果一个位置为负数,那么它下面的就都为负数。
如果一个位置为正数,那么这个左边的就都是正数。本题主要是为了统计负数,所以直接跳过即可
public static int countNegatives(int[][] grid) {
if (grid == null){
return 0;
}
int count = 0;
int col = grid.length;
int line = grid[0].length;
int x = 0; //当前行
int y = grid[0].length - 1; // 当前列
// 从右到左
while (x < col && y > -1){
int ele = grid[x][y];
if (ele >= 0){ //如果当前元素大于等于0: 当前元素之前的元素(包括当前元素)全部大于等于0
x++; // 进入下一行
}else{ // 当前当前元素小于0,那么当前元素下面的元素全部小于0
// 当前元素下面有多少的元素 = col - x
count = count + col - x;
y--;
}
}
return count;
}