题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样一个二维数组和一个整数,判断数组中是否含有这个整数。
二维数组举例:
1 2 8 9
2 4 9 12
4 7 10 13
6 8 11 15
当自己看到这个题目时,我的想法是,构建一个for循环,循环二维数组的行数次,由于每行是递增的有序数列,则采用二分查找的方法查找目标数据,接下来是自己实现的代码
int half_search(int *arr,int left,int right,int n,int i)
{
int mid = 0;
while(left <= right)
{
mid = left-(left-right)/2;
if(arr[i*4+mid] > n)
{
right = mid-1;
}
else if(arr[i*4+mid] < n)
{
left = mid+1;
}
else
{
return i*4+mid+1;
}
}
return -1;
}
bool test_search(int arr[4][4],int left,int right,int n)
{
int i = 0;
int ret = 0;
for(i = 0; i<4; i++)
{
ret = half_search(arr[i],left,right,n,i);
if(ret != -1)
{
return true;
}
}
return false;
}
int main()
{
int arr[4][4] = {{1,2,8,9},{2,4,9,12},{4,7,10,13},{6,8,11,15}};
int left = 0;
int right = 3;
int n;
scanf("%d",&n);
bool sr = test_search(arr,left,right,n);
if(sr == true)
{
printf("Yes\n");
}
else
{
printf("No\n");
}
system("pause");
return 0;
}
上述代码只能说是完成了题目的要求,但效率低,定义的变量以及中间函数太多,容易出错,自我感觉属于垃圾代码。
接下来,介绍金典的解题思路及代码
解题思路:
我们根据题目的每行每列数据都是递增且有序的,首先,选取数组中右上角的数字。如果该数字等于要查找的数字,查找结束;如果该数字小于要查找的数字,则该数字所在的行都不会存在该数字;如果该数字大于要查找的数子,则该数字所在的列都不会出现该数字;则在每一次的查找的过程中,都会剔除掉一行或则一列,不断缩小查找的范围,直到找到要查找的数字,或则查找的范围为空。
bool Find(int *arr,int rows,int columns, int n)
{
bool flags = false;
if(NULL != arr||rows > 0||columns > 0)
{
int i = 0;
int j = columns-1;
while(i<rows && j>=0)
{
if(arr[i*columns+j] <n)
{
i++;
}
else if(arr[i*columns+j] > n)
{
--j;
}
else
{
flags = true;
break;
}
}
}
return flags;
}