您的位置:首页 > 其它

二维数组的二分查找 解题报告

2012-09-02 22:05 302 查看
【题目大意】

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

【分析】

排好序的一维数组二分查找的效率是O(logN),本例中是二维数组,但是有序的性质可以使得在局部,即一维状况下继续使用二分查找,通过合理的组织查找区间可以再O(NlogM)的时间内找到是否存在该值key。

记二维数组(n行m列)为

A11A12……A1n
……………………
An1An2……Anm
则满足 :

A[i][1] <= A[i][2] <= ... <= A[i][m] ( i ∈ [1,n] )

A[1][j] <= A[2][j] <= ... <= A
[j] ( j ∈ [1,m] )

设待查找值可能在第i行,则必有A[i][1] <= key <= A[i][m]



①查找key可能在的行,由于在每一列都递增,故可能的行必然连在一起,即为一个区间[top,down],在这个区间有A[i][1] <= key <= A[i][m] ( i ∈ [top,down] )

通过二分查找可得出满足要求的[top,down]

②从第top行开始查找值key,一行一行往下搜,知道down的下一行或者搜到结果。采用如下搜法:

即当前在第cur行,在cur行的搜索区间为[left,right]( A[cur][left] <= key <= A[cur][right] )。

找到cur行在[left,right]区间中<=key的最大值的位置pos,若其==key,则返回找到,否则key不可能在本行,只可能在下面若干行中。

比较 A[cur+1][pos] 和 key

若其>key,则搜索区间为第cur+1行的[left,pos-1]。

若其 <key,则搜索区间为第cur+1行的[pos+1,key]。

否则找到。

如此往下搜,直到找到或者cur==down+1终止。

由上可知复杂度为O(nlogn)。

给个oj的链接:点击打开链接

附个代码:

#include <cstdlib>
#include <string.h>
#include <vector>
#include <set>
#include <iostream>
#include <stdio.h>
#include <queue>

using namespace std;

const int maxn = 1024 ;
int matrix[maxn][maxn] , n , m , key ;

inline bool get(int &t)
{
bool flag = 0 ;
char c;
while(!isdigit(c = getchar())&&c!='-') if( c == -1 ) break ;
if( c == -1 ) return 0 ;
if(c=='-') flag = 1 , t = 0 ;
else t = c ^ 48;
while(isdigit(c = getchar()))    t = (t << 1) + (t << 3) + (c ^ 48) ;
if(flag) t = -t ;
return 1 ;
}

/*返回第一个<=key的元素*/
int bs(int array[],int l,int r)
{
int mid ;
while (l<=r)
{
mid = (l+r) >> 1 ;
if( array[mid] > key ) r = mid-1 ;
else l = mid+1 ;
}
return r ;
}

bool query()
{
int topRow , downRow , i , j , l , r , mid , temp ;
l = 0 ; r = n-1 ;
/*找第一个<=key的*/
while (l<=r)
{
mid = (l+r) >> 1 ;
if( matrix[mid][0] > key ) r = mid-1 ;
else l = mid+1 ;
}
//[0,r]
if( r == -1 ) return false ;
if( matrix[r][0] == key ) return true ;
temp = r ;

l = 0 ; r = n-1 ;
/*找第一个>=key的*/
while (l<=r)
{
mid = (l+r) >> 1 ;
if( matrix[mid][m-1] >= key ) r = mid-1 ;
else l = mid+1 ;
}
//[l,n-1]
if( l == n ) return false ;
if( matrix[l][m-1] == key ) return true ;

r = temp ;
/*[0,r]和[l,n-1]无交集*/
if( r < l ) return false ;

topRow = l ;
downRow = r ;
/*interval is[topRow,downRow]*/

l = 0 ; r = m-1 ;
for ( i = topRow ; i <= downRow ; i++)
{
j = bs(matrix[i],l,r);
if( matrix[i][j] == key ) return true ;
if( i < downRow )
{
if( matrix[i+1][j] > key ) r = j ;
else if( matrix[i+1][j] < key ) l = j ;
else return true ;
}
}

return false ;
}

int main()
{
int i , j , k ;
while(get(n))
{
get(m);
get(key);
for ( i = 0 ; i < n ; i++)
for( j = 0 ; j < m ; j++)
get(matrix[i][j]);
printf("%s\n",query()?"Yes":"No");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: