编写一个高效的算法来判断
m x n
矩阵中,是否存在一个目标值。该矩阵具有如下特性:
- 每行中的整数从左到右按升序排列。
- 每行的第一个整数大于前一行的最后一个整数。
示例 1:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3 输出:true示例 2:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13 输出:false
提示:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 100
-104 <= matrix[i][j], target <= 104
与 剑指 Offer 04. 二维数组中的查找 有类似之处,可以使用https://blog.youkuaiyun.com/AHASAN/article/details/115309971?spm=1001.2014.3001.5501的双指针解法,但是显然本题比这道题多了个规律是每行第一个大于前一行最后一个,这是一个从左至右从上往下升序的二维数组,解决办法更多样。
/**
两次二分
先在第一列二分查找小于等于target的最大一行
再在上一步查找到的行二分查找target值
**/
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int row=matrix.length,i=-1,j=row-1,mid=0;
if(row==0)return false;
int column=matrix[0].length;
while(i<j){//避免死循环,不设置等于条件,i值不作增减
mid=(j-i-1)/2+i+1;//i初始化为-1进行单行单列数组的target判断,在计算时还原为0开始
if(mid==i)break;//避免死循环
if(matrix[mid][0]<=target){
i=mid;//如果小于等于,则保留当前索引
}else{
j=mid-1;
}
}
if(i<0)return false;//没有找到小于等于target的索引
row=i;
i=0;
j=column-1;
while(i<=j){
mid=(j-i)/2+i;
if(matrix[row][mid]<target){
i=mid+1;
}else if(matrix[row][mid]>target){
j=mid-1;
}else{
return true;
}
}
return false;
}
}
/**
一次二分查找
将二维数组从左至右从上至下拼接成一个一维数组(颅内想象就好,不用真拼,真拼不就暴力了吗,直接判断等于就好了,还二分什么二分!愚蠢的我!
根据一维数组的索引index,得到当前值对应原二维数组的横纵坐标x,y
x=index/column
y=index%column
懂自懂,不多说!
**/
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int row=matrix.length;
int column=matrix[0].length;
int low=0,high=row*column-1,mid=0,i=0,j=0;
while(low<=high){
mid=(high-low)/2+low;
i=mid/column;
j=mid%column;
if(i>=row)return false;
if(matrix[i][j]<target){
low=mid+1;
}else if(matrix[i][j]>target){
high=mid-1;
}else{
return true;
}
}
return false;
}
}