二维数组的查找
Time Limit: 2000/1000ms (Java/Others)
Problem Description:
给定一个n*m的二维数组,保证a[i][j] < a[i+1][j],a[i][j]< a[i][j+1](其中0≤i< n-1,0≤j< m-1);
接下来有q个询问,每个询问包含一个数字num,查找num是否包含在该二维数组里面。
Output:
对于每组数据,对于每个询问如果num在二维数组里,输出Yes,否则输出No。
Sample Input:
4 3
1 2 8
2 4 9
4 7 10
6 8 11
3
5
4
10
Sample Output:
No
Yes
Yes
解题思路:二维数组的查找,题目中给出的矩阵最大为10^3*10^3,暴力查找显然会超时。但解题的关键在于标红色的条件,即每一行是升序,每一列也是升序,所以根据这个特点,查找的起始点应从右上角开始,向左边和下边进行扫描比较,这样可以节省很多时间。①显然当a[i][j]>num时,说明当前行num可能在当前行,于是j--向左扫描;②当a[i][j]<num时,说明当前行所在列的值比较小,于是i++进入下一行进行比较,③最后相等时,只需做一个标记看是否矩阵中存在这个元素即可。这里可能对②这种情况会有疑问,我们简单拿3*3矩阵举个栗子:
3 6 -- 11
|
4 7 12
|
5 8 13
如果我们要查找元素9是否在矩阵中,首先11>9,于是--j,然后6<9,于是++i,解决疑问就在这里,因为11所在列是升序,即11<12,所以当num>a[i][j](9>6)++i之后,即现在第二行所在列(比如:12)之后肯定比num大,所以不用去比较剩下的列元素。当9与8比较完之后,由于9>8,所以++i就导致越界,于是退出循环,表示矩阵中没有9这个元素。
AC代码:
1 #include<bits/stdc++.h>
2 using namespace std;
3 int a[1005][1005],n,m,q,num;bool flag;//标记是否找到
4 int main()
5 {
6 while(cin>>n>>m){
7 for(int i=0;i<n;++i)
8 for(int j=0;j<m;++j)
9 cin>>a[i][j];
10 cin>>q;
11 while(q--){
12 cin>>num;flag=false;
13 for(int i=0,j=m-1;!flag && i<n && j>=0;){
14 if(a[i][j]==num)flag=true;
15 else if(a[i][j]<num)++i;
16 else --j;
17 }
18 if(flag)cout<<"Yes"<<endl;
19 else cout<<"No"<<endl;
20 }
21 }
22 return 0;
23 }