得分:20
根据行列递增的特点,逐步缩小范围,首先在首行和首列中查找小于或等于查找值的行或列,舍去大的部分,再在尾行和尾列中查找大于或等于查找值的行或列,舍去小的部分,循环处理,直到剩下一个元素,比对。
#include
int data[5][6] =
{
{1, 4, 7, 11, 15,25},
{2, 5, 8, 12, 19,28},
{3, 6, 9, 16, 22,31},
{10, 13, 14, 17, 24,32},
{18, 21, 23, 26, 30,39}
};
int m=5,n=6;
int main()
{
int x;
int f(int);
while(x!=-1)
{
scanf("%d",&x);
printf("%s\n",(f(x)==1)?"true":"false");
}
}
int f(int x)
{
int si,sj,ei,ej;
int s,e,k;
si=0;
sj=0;
ei=m-1;
ej=n-1;
while((ei-si>0)|(ej-sj>0))
{
if(data[si][sj]>x) return 0;
//用二分查找在首行中查找<=x的列号
s=sj;
e=ej;
if(data[si][e]<=x) s=e;
while(e-s>1)
{
k=s+(e-s)/2;
if (data[si][k]>x) e=k;
else s=k;
}
ej=s;//更改尾列下标,缩小范围
//用二分查找在首列中查找<=x的行号
s=si;
e=ei;
if(data[e][sj]<=x) s=e;
while(e-s>1)
{
k=s+(e-s)/2;
if (data[k][sj]>x) e=k;
else s=k;
}
ei=s;//更改尾行下标,缩小范围
if(data[ei][ej]
//用二分查找在尾行中查找>=x的列号
s=sj;
e=ej;
if(data[ei][s]>=x) e=s;
while(e-s>1)
{
k=s+(e-s)/2;
if (data[ei][k]
else e=k;
}
sj=e;//更改首列下标,缩小范围
//用二分查找在尾列中查找>=x的行号
s=si;
e=ei;
if(data[s][ej]>=x) e=s;
while(e-s>1)
{
k=s+(e-s)/2;
if (data[k][ej]
else e=k;
}
si=e;//更改首行下标,缩小范围
}
return data[si][sj]==x;//此时si=sj,ei=ej
}