题目描述:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
1.原始解法:
/*
描述:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。
请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
时间:2019-07-24 11:29
函数名:findInTwoDimArray
*/
bool findInTwoDimArray(int* matrix, int rows, int colum, int number)
{
bool found = false;
if (matrix != NULL && rows > 0 && colum > 0)
{
int row = 0;
int col = colum - 1;
while (row<rows && col>=0)
{
if (matrix[row*colum + col] == number)
{
found = true;
break;
}
else if (matrix[row*colum + col] > number)
{
--col;
}
else
{
++row;
}
}
}
return found;
}
这种解法在二维数组有序的基础上,充分利用了数组行列的特征,迅速缩小在数组上搜索的规模,每次在循环的过程中,必然会伴随着行和列的范围缩减。具体细节不做解释,想了解的话可以 参考《剑指offer》面试问题4。
2.结合二分查找的搜索方法
/*
描述:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。
请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
时间:2019-07-24 11:29
函数名:findInTwoDimArrayWithBinary
备注:查找改为二分查找
*/
bool findInTwoDimArrayWithBinary(int* matrix, int rows, int colum, int number)
{
bool found = false;
if (NULL != matrix && rows > 0 && colum > 0)
{
//数组的右上角下标
int row = 0;
int col = colum - 1;
//行的二分查找边界
int left = 0;
int right = rows - 1;
while (row < rows && col >= 0)
{
if (number > matrix[row*colum + colum-1]) //减少检索次数,意义不是很大
{
++row;
left = 0;
}
else if (number < matrix[row*colum])
{
break;
}
int mid = ((right - left) >> 1) + left;
if (number == matrix[row*colum + mid])
{
found = true;
break;
}
else if (number > matrix[row*colum + mid]) //查找元素大于数组元素时处理行列变化
{
if (left == mid && right == mid)
//此时,查找元素介于matrix[row*colum + mid]与matrix[row*colum + mid+1]之间,且 matrix[row*colum + mid+1]已经遍历,因而行+1,列缩减到检索位置
{
++row;
col = mid;
left = 0;
right = col;
}
else //正常的行搜索
{
left = mid + 1;
}
}
else if (number < matrix[row*colum + mid])
{
if (left == mid) //此时查找元素小于matrix[row*colum + mid],因而行+1,列缩减到检索位置-1。
{
++row;
col = mid - 1;
left = 0;
right = col;
}
else
{
right = mid - 1;
}
}
}
}
return found;
}
这种处理方法充分利用了数组行列有序的特征,结合二分查找快速缩减行和列,对于处理大量数据,效率较高。在结合二分查找的过程中,需要特别注意行列缩减时的条件。可以借助图示或者代码调试来确定变化条件。