74. 搜索二维矩阵
编写一个高效的算法来判断 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
方法一:排序+二分
一种极其沙雕的做法,复杂度极高,但很容易想。
bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target){
int*res = (int*)malloc(sizeof(int)*10000);
int k = 0;
for(int i=0;i<matrixSize;i++)
{
for(int j=0;j<matrixColSize[0];j++)
{
res[k++] = matrix[i][j];
}
}
int left = 0;
int right = k-1;
int mid;
while(left<=right)
{
mid = left+(right-left)/2;
if(res[mid]>target)
{
right = mid-1;
}
if(res[mid]<target)
{
left = mid+1;
}
if(res[mid]==target)
{
free(res);
return 1;
}
}
free(res);
return 0;
}
方法二:n次二分
即每一行我们都进行一次二分查找,若能找到则跳出,找不到继续。
bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target){
for(int i=0;i<matrixSize;i++)
{
int left = 0;
int right = matrixColSize[0]-1;
int mid;
while(left<=right)
{
mid = left+(right-left)/2;
if(matrix[i][mid]>target)
{
right = mid-1;
}
if(matrix[i][mid]<target)
{
left = mid+1;
}
if(matrix[i][mid]==target)
{
return 1;
}
}
}
return 0;
}
方法三:两次二分
由于二维矩阵的特殊性,我们可以先对每一行的头部元素进行一个二分查找,查找到最贴近目标值且比它大的那一行时停止查找,对此行再次进行一个二分查找即可,因为目标值必定在其中。
bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target){
int left = 0;
int right = matrixSize-1;
int mid;
while(left<right)
{
mid = left+(right-left+1)/2;//不多搞1则会卡住
if(matrix[mid][0]>target)
{
right = mid-1;
}
if(matrix[mid][0]<=target)
{
left = mid;
}
}
int temp = left;
left = 0;
right = matrixColSize[0]-1;
while(left<=right)
{
mid = left+(right-left)/2;
if(matrix[temp][mid]>target)
{
right = mid-1;
}
if(matrix[temp][mid]<target)
{
left = mid+1;
}
if(matrix[temp][mid]==target)
{
return 1;
}
}
return 0;
}
方法四:一次二分
我们可以将有序二维转化为有序一维,继而对此一维数组进行一次二分即可。
即用降维后的mid除以每行所拥有的列数,即可得到其行数;
用mid除以每行所拥有的列数取余数,则得到其所在列数;
bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target){
int left = 0;
int m = matrixSize;
int n = matrixColSize[0];
int right = m*n-1;
int mid;
while(left<=right)
{
mid = left+(right-left)/2;
if(matrix[mid/n][mid%n]>target)
{
right = mid-1;
}
if(matrix[mid/n][mid%n]<target)
{
left = mid+1;
}
if(matrix[mid/n][mid%n]==target)
{
return 1;
}
}
return 0;
}