抛开对知识、学问的依赖心理,是你走上人生康庄大道的关键。
本篇文章所涉及的算法题:
1. 解题技巧
-
定义行(Row)和列(Column):
- rows = matrix.length;
- cols = martrix[0].length;
-
矩阵的遍历
for(int i = 0;i < rows;i++){ for(int j = 0; j < cols;j++){ // TODO ![在这里插入图片描述](https://img-blog.csdnimg.cn/487fae0eddd34646b2fa2ff950412335.webp#pic_center) } }
2. 案例
本篇文章主要用来讨论总结一下处理矩阵中查找目标元素的方案。
240. 搜索二维矩阵 II
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。
该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
如图所示:
1. 解法
利用题目中矩阵的特点,选中左上角作为起始点来遍历。
时间复杂度:O(m+n)
public boolean searchMatrix(int[][] matrix, int target) {
// 1. 处理边界
if(matrix == null || matrix.length == 0){
return false;
}
// 处理矩阵题目的好规范:优先把行数、列数给统计出来
int rows = matrix.length;
int cols = matrix[0].length;
// 选用『左上角』为起始点
int i = 0;
int j = cols-1;
while(i < rows && j >= 0){
if(matrix[i][j] == target){
return true;
}
if(matrix[i][j] < target){
i++;
}else{
j--;
}
}
return false;
}
74. 搜索二维矩阵
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。
该矩阵具有如下特性:每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。
PS: 注意此题与 240. 搜索二维矩阵 II的区别。
此题展开是一个有序的一维数组。
1. 解法一(O(m+n))
上面的解法依然可以解决此题
public boolean searchMatrix(int[][] matrix, int target) {
if(matrix == null || matrix.length == 0){
return false;
}
int rows = matrix.length;
int cols = matrix[0].length;
int i = 0;
int j = cols- 1;
while(i < rows && j >= 0){
if(matrix[i][j] == target){
return true;
}
if(matrix[i][j] > target){
j--;
}else{
i++;
}
}
return false;
}
2. 解法二(O(log(m) + log(n)) - 最优解
初中知识都没忘吧 :log(m) + log(n) = log(mn)
根据题目的描述,可以得出该矩阵展开为一个递增有序的一维数组。
聪明的你一定知道,看到有序,就要联想到二分法(BinarySearch)。
public boolean searchMatrix(int[][] matrix, int target) {
// 将二维数组看作是一维的
if(matrix == null || matrix.length == 0){
return false;
}
int rows = matrix.length;
int cols = matrix[0].length;
int left = 0;
int right = rows * cols - 1;
while(left <= right){
int mid = left + (right-left)/2;
// 核心:根据mid在一维数组中的位置 推导出其在矩阵中的位置。
int i = mid / cols;
int j = mid % cols;
if(matrix[i][j] == target){
return true;
}
if(matrix[i][j] < target){
left = mid + 1;
}else{
right = mid - 1;
}
}
return false;
}
1351. 统计有序矩阵中的负数
给你一个 m * n 的矩阵 grid,矩阵中的元素无论是按行还是按列,都以非递增顺序排列。
请你统计并返回 grid 中 负数 的数目。
如下图所示:
此题依然选择从左上角作为出发点,因为如果如果第一行的某一列小于0,则可以得出整列都是小于0的。
解法
public int countNegatives(int[][] grid) {
if(grid == null || grid.length == 0){
return 0;
}
int rows = grid.length;
int cols = grid[0].length;
int i = 0;
int j = cols-1;
int result = 0;
while(i < rows && j >= 0){
if(grid[i][j] < 0){
result+=(rows-i);
j--;
}else{
i++;
}
}
return result;
}