本題來自《劍指offer》面試題3
題目描述:
在一個二維數組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。
- 輸入:
-
輸入可能包含多個測試樣例,對於每個測試案例,
輸入的第一行爲兩個整數m和n(1<=m,n<=1000):代表將要輸入的矩陣的行數和列數。
輸入的第二行包括一個整數t(1<=t<=1000000):代表要查找的數字。
接下來的m行,每行有n個數,代表題目所給出的m行n列的矩陣(矩陣如題目描述所示,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。
- 輸出:
-
對應每個測試案例,
輸出”Yes”代表在二維數組中找到了數字t。
輸出”No”代表在二維數組中沒有找到數字t。
樣例輸入:
3 3
5
1 2 3
4 5 6
7 8 9
3 3
1
2 3 4
5 6 7
8 9 10
3 3
12
2 3 4
5 6 7
8 9 10
樣例輸出:
Yes No No
思路:對於這種二維數組查找,如果從最左上角[0][0]向中間走,每一步都會有兩種方向可能。這樣問題越來越複雜。如果抱着從右上角或者左下角思路開始分析,顯然每次可以排除一列的值。如果[i][j]比右上角的值小,則本列已經不可能有target了。如果大,則本行已經不可能有target了。這個問題啓示我們當有多個路徑可選時,換一個邊界入手,形成相互約束,減少考慮分支。
提交代碼:Time Limit Exceed
<span style="font-size:12px;">#include<iostream>
using namespace std;
bool search(int (*a)[1000],int m,int n,int target)
{
int i=0,j=n-1;
while(i<m && n>0){
if(a[i][j]==target)return 1;
else {
if(a[i][j]>target)j--;
else
i++;
}
}
return 0;
}
int main()
{
int m,n,target,a[1000][1000];
while(cin>>m>>n)
{
cin>>target;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
cin>>a[i][j];
if(search(a,m,n,target))
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
return 0;
}</span>
居然將cin改爲scanf就不超時了
#include<iostream>
#include <cstdio>
using namespace std;
bool search(int (*a)[1000],int m,int n,int target)
{
int i=0,j=n-1;
while(i<m && n>0){
if(a[i][j]==target)return 1;
else {
if(a[i][j]>target)j--;
else
i++;
}
}
return 0;
}
int main()
{
int m,n,target,a[1000][1000];
while(scanf("%d %d",&m,&n)!=EOF){
scanf("%d",&target);
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
scanf("%d",&a[i][j]);
if(search(a,m,n,target))
printf("Yes\n");
else
printf("No\n");
}
return 0;
}