我的LeetCode代码仓:https://github.com/617076674/LeetCode
原题链接:https://leetcode-cn.com/problems/search-a-2d-matrix/description/
题目描述:
知识点:二分查找法
思路一:运用两次二分查找法
注意初值条件,如果矩阵的行数或者列数为0,直接返回false。
第一次二分查找法,是在矩阵的第一列元素里查找target的floor值。如果target比矩阵(0, 0)位置的值还要小,floor函数会返回-1,直接返回false。如果target比矩阵最后一行的第一列元素的值还要大,floor函数会返回最后一行的行号。
我们根据floor函数返回的行号,在matrix矩阵对应行二分搜索查找target的值。如果找到,直接返回true。否则,返回false。
时间复杂度是O(logm + logn),其中m为矩阵的行数,n为矩阵的列数。空间复杂度是O(m)。
JAVA代码:
public class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int m = matrix.length;
if(m == 0){
return false;
}
int n = matrix[0].length;
if(n == 0){
return false;
}
int[] array = new int[m];
for (int i = 0; i < m; i++) {
array[i] = matrix[i][0];
}
int row = floor(array,target);
if(row == -1){
return false;
}
return binarySearch(matrix[row],target);
}
private boolean binarySearch(int[] array, int target){
int left = 0, right = array.length - 1;
while(left <= right){
int mid = left + (right - left) / 2;
if(array[mid] == target){
return true;
}else if(array[mid] < target){
left = mid + 1;
}else{
right = mid - 1;
}
}
return false;
}
private int floor(int[] array, int target){
int left = -1;
int right = array.length - 1;
while(left < right){
int mid = left + (right - left + 1) / 2;
if(array[mid] < target) {
left = mid;
}else{
right = mid - 1;
}
}
if(left + 1 < array.length && array[left + 1] == target){
return left + 1;
}else{
return left;
}
}
}
LeetCode解题报告:
思路二:将思路一中的floor()函数换成ceil()函数
ceil()函数的实现可以参见LeetCode034——在排序数组中查找元素的第一个和最后一个位置。
时间复杂度是O(logm + logn),其中m为矩阵的行数,n为矩阵的列数。空间复杂度是O(m)。
JAVA代码:
public class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int m = matrix.length;
if(m == 0){
return false;
}
int n = matrix[0].length;
if(n == 0){
return false;
}
int[] array = new int[m];
for (int i = 0; i < m; i++) {
array[i] = matrix[i][n - 1];
}
int row = ceil(array,target);
if(row == m){
return false;
}
return binarySearch(matrix[row], target);
}
private boolean binarySearch(int[] array, int target){
int left = 0, right = array.length - 1;
while(left <= right){
int mid = left + (right - left) / 2;
if(array[mid] == target){
return true;
}else if(array[mid] < target){
left = mid + 1;
}else{
right = mid - 1;
}
}
return false;
}
private int ceil(int[] array, int target){
int left = 0;
int right = array.length;
while(left < right){
int mid = left + (right - left) / 2;
if(array[mid] < target) {
left = mid + 1;
}else{
right = mid;
}
}
if(right - 1 >= 0 && array[right - 1] == target){
return right - 1;
}else{
return right;
}
}
}
LeetCode解题报告: