您的位置:首页 > 编程语言 > C语言/C++

剑指offer面试题:二维数组中的查找,C语言实现

2014-10-27 17:45 555 查看
我是从九度OJ上面看到这个题目的,如果只是简单的想AC这道题目,介于OJ平台只关注输入输出,则很容易AC这道题目。我是把这道题目看做是一道面试题来解决的,先来看下题目吧:

题目描述:
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

输入:
输入可能包含多个测试样例,对于每个测试案例,

输入的第一行为两个整数m和n(1<=m,n<=1000):代表将要输入的矩阵的行数和列数。

输入的第二行包括一个整数t(1<=t<=1000000):代表要查找的数字。

接下来的m行,每行有n个数,代表题目所给出的m行n列的矩阵(矩阵如题目描述所示,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。

输出:
对应每个测试案例,

输出”Yes”代表在二维数组中找到了数字t。

输出”No”代表在二维数组中没有找到数字t。

下面来分析一下思路:

首先,因为数组的每一行和每一列都是递增的所以可以发现如下的规律:



数字7是大矩阵的最小值,13是小矩阵的最小值,所以我们的思路就是先让查找的数x跟二维数组的对角线上的值进行比较(找到数组中对角线上第一个大于x的数的位置来缩小查找的范围)比如,我们查找12,那么查找的范围就可以锁定在两个部分,如下图所示:



此时,我们只要在这两部分中查找x即可,观察可发现这两个部分一个是一行数据(可视为一维数组)和一个是小矩阵。前一部分可以用二分查找(有序),后一部分可以直接遍历(应该还有更好的方法,我实现的时候是直接遍历)。

由于题目对m和n的大小关系没有做限制,这就增加了题目的难度(即找到二维数组中第一个大于x的数的位置边困难了),我的解决思路是根据m和n的大小关系分三种情况,

当m=n时最简单,在此不提,另外两种情况,分别是找一个小的方型矩阵,如果没有找到要找的位置,那么改变循环变量的值,继续在下一个小方型矩阵中寻找,直到没有小的方型矩阵为止。下面给出一个m>n的大致查找过程:



主要解题思路如上所述,下面给出C语言实现的完整代码(附注释)

#include<stdio.h>
#include<stdlib.h>
long a[1000][1000];
int m,n;
//二分查找
int binarySearch(int tm1,int tn1,long x)
{
int s,e,mid;
s=tn1+1;
e=n-1;
while(s<=e)
{
mid=(s+e)/2;
if(a[tm1][mid]==x)
return 1;
else if(a[tm1][mid]<x)
{
s=mid+1;
}
else
{
e=mid-1;
}
}
return 0;
}
//小矩阵遍历
int binarySearch2(int tm2,int tn2,long x)
{
int i,j;
for(i=tm2;i<m;++i)
for(j=0;j<=tn2;++j)
if(a[i][j]==x)
return 1;
return 0;
}
int arraySearch(long x)
{
int tm,tn;
int r1,r2;
if(m>n)
{
tm=0;
tn=0;
//查找位置的过程
while(tm<m)
{
if(a[tm][tn]==x)
{
return 1;
}
if(a[tm][tn]>x)
{
break;
}
if(tn==n-1)
{
tn=0;
++tm;//进入下一个小型方阵
}
else
{
++tn;
++tm;
}
}
//查找位置的过程
if(tm==m)
{
return binarySearch(tm-1,0,x);
}
else
{
//找到位置后,分别对两部分进行查找
r1=binarySearch(tm-1,tn-1,x);//二分查找
r2=binarySearch2(tm,tn-1,x);//小矩阵遍历
return (r1+r2);
}
}
else if(m<n)
{
tm=0;
tn=0;
while(tn<n)
{
if(a[tm][tn]==x)
{
return 1;
}
if(a[tm][tn]>x)
{
break;
}
if(tm==m-1)
{
tm=0;
++tn;
}
else
{
++tn;
++tm;
}
}
if(tn==n)
{
return binarySearch2(tn-1,0,x);
}
else
{
r1=binarySearch(tm-1,tn-1,x);
r2=binarySearch2(tm,tn-1,x);
return (r1+r2);
}
}
else
{
tm=0;
tn=0;
while(tm<m)
{
if(a[tm][tn]==x)
{
return 1;
}
if(a[tm][tn]>x)
{
break;
}
++tn;
++tm;
}
if(tm==m)
{
return 0;
}
else
{
r1=binarySearch(tm-1,tn-1,x);
r2=binarySearch2(tm-1,tn-1,x);
return (r1+r2);
}
}
}
int main()
{
int i,j;
long x;
while(scanf("%d %d",&m,&n)!=EOF)
{
scanf("%ld",&x);
for(i=0;i<m;++i)
for(j=0;j<n;++j)
{
scanf("%ld",&a[i][j]);
}
if(arraySearch(x))
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}

return 0;
}


在oj测试,AC通过,可能还有没有考虑到的地方,欢迎指正,共同学习。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: