前几天参加了深信服的笔试,第一题就是这个检测小矩阵在大矩阵中是否存在。
当时想法是有的,不过具体实现出了点问题,笔试应该挂了。
时隔两天,我还是觉得要把题目弄完,也算是一种积累吧。
愿你我都能遇见最好的自己。
题目描述
- 请输入一个数T,表示接下来要输入的矩阵组数。T<50
- 在一行内输入两个整数N、M,他们分别表示大矩阵(方阵)和小矩阵(方阵)的阶数。 0<N<10000; 0<M<=N.
- 输出T行:即每一组的结果输出一行,如果小矩阵存在于大矩阵中,则输出 yes, 若是小矩阵不在大矩阵中,则输出 no.
- 实例:
输入:
1
3 2
# . #
. # .
# # #
# .
. #
输出:
yes
输入组数为3:
3
3 2
# . #
. # .
# # #
# .
. #
3 2
# . #
. # .
# # #
. #
# #
3 2
# . #
. # .
# # #
# #
. #
输出:
yes
yes
no
要完成的工作就是以上所述。接下来我将使用矩阵的双指针法来完成该任务。
代码实现
//NiuBiVirus
#include<iostream>
using namespace std;
int main(){
int n;
cin>>n; //输入的组数n
if(n<1 || n>50){
cout<<"输入不符合规则"<<endl;
return 0;
}
int i=0;
int N,M; //分别定义数组的大小
while(i<n){
i++;
cin>>N>>M;
char s1[N][N]; //定义数组 1 并用 for循环输入
for(int j=0;j<N;j++){
for(int k=0;k<N;k++){
cin>>s1[j][k];
}
}
char s2[M][M]; //定义数组 2 并用 for循环输入
for(int j=0;j<M;j++){
for(int k=0;k<M;k++){
cin>>s2[j][k];
}
}
//测试输出
// for(int j=0;j<N;j++){
// for(int k=0;k<N;k++){
// cout<<s1[j][k]<<' ';
// }
// cout<<endl;
// }
int l1=0,l2=0; // 用数字定义数组1的指针
int k1=0,k2=0; // 用数字定义数组2的指针
int d1=0,d2=0; // 用于锚定数组1对应数组2头部的位置
int key=0; // 一个记录全正确比较的值
int ch=0;
while(1){
if(ch==1){ //设定判别参数判定锚点是否更改
d1=l1;
d2=l2;
}
if(s1[l1][l2]==s2[k1][k2]){ //比较数组1与数组2的指针域指向的值是否相等
key++;
ch=0;
l2++; //若相等则数组1和数组2的指针都向后移动
k2++;
if(k2==M){ //若数组2的指针溢出,则指针换行
l1++;
l2=l2-M; //注意换行后数组1的指针指向,应与上一行的位置联系起来
k1++;
k2=0;
}
if(k1==M){ //若数组2的列指针溢出,则比较完成。
cout<<"yes"<<endl;
break;
}
}
else {
ch = 1;
if(l2>0){ //注意指针的变化情况,若在上面改变了指针应改回来再执行后续
l2--;
k2--;
}
key=0; // key值清零表示需从头再全部比较数组2
d2++; //数组1与2的对应值不相等时,移动大数组的锚点指针
k2=0;
if(d2==N-M+1){ // 若发现大数组剩下的列数小于小矩阵时可直接换行
d1++;
d2=0;
k1=0;
k2=0;
}
if(d1==N-M+1){ // 若发现大数组剩下的矩阵小于小矩阵时可直接结束
cout<<"No"<<endl;
break;
}
l1=d1;
l2=d2;
}
// cout<<"l1:"<<l1<<endl;
// cout<<"l2:"<<l2<<endl;
// cout<<"k1:"<<k1<<endl;
// cout<<"k2:"<<k2<<endl;
// cout<<"key:"<<key<<endl;
// cout<<endl;
}
// key值比较。
// if(key==M*M){
// cout<<11111111;
// }
// else cout<<22222222;
}
return 0;
}
运行结果
如上图,题目要求的任务能够实现,不过输出于输入是交叉进行,可做适当修改美化输出。
优化后的代码
//NiuBiVirus
#include<iostream>
using namespace std;
int main(){
int n;
cin>>n; //输入的组数n
if(n<1 || n>50){
cout<<"输入不符合规则"<<endl;
return 0;
}
int i=0;
int N,M; //分别定义数组的大小
//优化输出:
int res[n] = {0};
while(i<n){
cin>>N>>M;
char s1[N][N]; //定义数组 1 并用 for循环输入
for(int j=0;j<N;j++){
for(int k=0;k<N;k++){
cin>>s1[j][k];
}
}
char s2[M][M]; //定义数组 2 并用 for循环输入
for(int j=0;j<M;j++){
for(int k=0;k<M;k++){
cin>>s2[j][k];
}
}
int l1=0,l2=0; // 用数字定义数组1的指针
int k1=0,k2=0; // 用数字定义数组2的指针
int d1=0,d2=0; // 用于锚定数组1对应数组2头部的位置
int key=0; // 一个记录全正确比较的值 !! 优化后可省略该参数
int ch=0; // 用于判断是否更换锚点的参数
while(1){
if(ch==1){ //设定判别参数判定锚点是否更改
d1=l1;
d2=l2;
}
if(s1[l1][l2]==s2[k1][k2]){ //比较数组1与数组2的指针域指向的值是否相等
key++;
ch=0;
l2++; //若相等则数组1和数组2的指针都向后移动
k2++;
if(k2==M){ //若数组2的指针溢出,则指针换行
l1++;
l2=l2-M; //注意换行后数组1的指针指向,应与上一行的位置联系起来
k1++;
k2=0;
}
if(k1==M){ //若数组2的列指针溢出,则比较完成。
// cout<<"yes"<<endl; //优化前
res[i] = 1; //优化后
break;
}
}
else {
ch = 1;
if(l2>0){ //注意指针的变化情况,若在上面改变了指针应改回来再执行后续
l2--;
k2--;
}
key=0; // key值清零表示需从头再全部比较数组2
d2++; //数组1与2的对应值不相等时,移动大数组的锚点指针
k2=0;
if(d2==N-M+1){ // 若发现大数组剩下的列数小于小矩阵时可直接换行
d1++;
d2=0;
k1=0;
k2=0;
}
if(d1==N-M+1){ // 若发现大数组剩下的矩阵小于小矩阵时可直接结束
// cout<<"No"<<endl; // 优化前
res[i]=0; // 优化后
break;
}
l1=d1;
l2=d2;
}
}
i++;
}
cout<<"输出行数为:"<<n<<endl;
for(int x=0;x<n;x++){
if(res[x]==1){
cout<<"yes"<<endl;
}
else cout<<"no"<<endl;
}
return 0;
}
优化后的输出结果
至此该任务也算完成啦,希望后面遇到问题能够披荆斩棘!!!
加油年轻人,冲冲冲!!!