我们仔细分析,不难发现,对于杨氏矩阵老说,右上角和左下角的元素是有特点的。右上角的元素是一行中最大的,一列中最小的。左下角的元素是一行中最小的,是一列中最大的。所以我们可以从右上角或者左下角开始查找。比如:从右上角开始查找的时候,右上角的元素比我们要查找元素小,我们就可以去掉右上角元素所在的这一行;右上角的元素比我们要查找的元素大,我们就可以去掉右上角元素所在的这一列。然后依然找右上角的元素继续和要查找的元素与比较。这样每一次比较去掉一行或者去掉一列。这个查找效率是高于遍历数组元素的,所以时间复杂度是小于O(N),也满足题目要求。
最终效果:
初步代码实现:
#include <stdio.h>
int findnum(int a[][3], int x, int y, int f) //第一个参数的类型需要调整,因为二维数组的行可以省略,列不能省略。
{
int i = 0, j = y - 1; //从右上角开始遍历
while (j >= 0 && i < x)
{
if (a[i][j] < f) //比我大就向下
{
i++;
}
else if (a[i][j] > f) //比我小就向左
{
j--;
}
else//如果不大不小那就是找到了
{
return 1;//找到了就返回1
}
}
return 0;//没找到就返回0
}
int main()
{
int a[][3] = { {1, 3, 5},//一个二维数组
{3, 5, 7},
{5, 7, 9} }; //一个示例
if (findnum(a, 3, 3, 2)==1)//a是二维数组首元素地址,实际上就是a[0][0]a,3,3是3行3列,2是我们要在矩阵中查找的值
{
printf("It has been found!\n");//如果返回1的话就显示找到
}
else
{
printf("It hasn't been found!\n");//否则返回0的话就显示没有找到;
}
return 0;
}
运行结果:
因为我们的这个数组里没有2
int a[][3] = { {1, 3, 5},//一个二维数组
{3, 5, 7},
{5, 7, 9} }; //一个示例
假设我们把要查找的值换成数组里面存在的值:3
if (findnum(a, 3, 3, 3)==1)//a是二维数组首元素地址,实际上就是a[0][0]a,3,3是3行3列,2是我们要在矩阵中查找的值
{
printf("It has been found!\n");//如果返回1的话就显示找到
}
else
{
printf("It hasn't been found!\n");//否则返回0的话就显示没有找到;
}
运行结果:
显示找到了。
但是这样我们发现还是不方便,假如我们想换数组,就需要我们重新设置数组的值,想要更换查询的数字也需要更换,比较麻烦。干脆直接用scanf去输入算了。
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
scanf("%d",&a[i][j]);//输入二维数组
printf("%d ",a[i][j]);//把我们输入的二维数组打印成矩阵
}printf("\n");
}
int n=0;
printf("请输入一个数:");
scanf("%d",&n);//输入我们的n值
if (findnum(a, 3, 3, n))//直接传过去一个n值,n就是我们要查找的数字。
{
printf("It has been found!\n");
}
else
{
printf("It hasn't been found!\n");
}
return 0;
}
运行结果:
但是,实际上这个代码还是存在问题的,比如说我们这样输入会怎么样:9 8 7 6 5 4 3 2 1
我们发现4明明是存在于矩阵中的,但是运行结果却显示没有找到。
这是因为我们杨氏矩阵的前提是:右上角和左下角的元素是有特点的。右上角的元素是一行中最大的,一列中最小的。左下角的元素是一行中最小的,是一列中最大的。
而如果是逆序打印矩阵的话就不能按这种查找方式了。
所以我们需要对矩阵进行升序排序,让它升序方式打印输出.为了方便,我们直接qsort快排。
qsort(a,9,sizeof(int),cmpunc);
int cmpunc(const void* a,const void* b)
{
return (*(int*)a-*(int*)b);
}
看一下运行效果:
可以正常找到n值了。
然后我们再设置一个goto 语句,假如矩阵里没有我们输入的n值,那么就让我们重新输入n,直到找到n值为止。
again:
printf("请输入一个数:");
scanf("%d",&n);
if (findnum(a, 3, 3, n))
{
printf("It has been found!\n");
}
else
{
printf("It hasn't been found!\n");
goto again;
}
return 0;
}
最终代码:
#include <stdio.h>
#include<stdlib.h>
int findnum(int a[][3], int x, int y, int f) //第一个参数的类型需要调整,因为二维数组的行可以省略,列不能省略。
{
int i = 0, j = y - 1; //从右上角开始遍历
while (j >= 0 && i < x)
{
if (a[i][j] < f) //比我大就向下
{
i++;
}
else if (a[i][j] > f) //比我小就向左
{
j--;
}
else//如果不大不小那就是找到了
{
return 1;//找到了就返回1
}
}
return 0;//没找到就返回0
}
int cmpunc(const void* a,const void* b)
{
return (*(int*)a-*(int*)b);//(*(int*)a-*(int*)b)就是升序。(*(int*)b-*(int*)a)就是降序
}
int main()
{
int i=0;
int j=0;
int n=0;
int a[3][3];
printf("请输入一组数字:");
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
scanf("%d",&a[i][j]);//输入一个二维数组
}printf("\n");
}
qsort(a,9,sizeof(int),cmpunc);//qsort快排
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%d ",a[i][j]);//把升序之后的矩阵打印出来
}printf("\n");//i执行一次,j执行5次就换行一次,i执行3次,j执行15次就是个矩阵
}
again://again重新输入n值
printf("请输入一个数:");
scanf("%d",&n);
if (findnum(a, 3, 3, 2)==1)//a是二维数组首元素地址,实际上就是a[0][0]a,3,3是3行3列,2是我们要在矩阵中查找的值
{
printf("It has been found!\n");//如果返回1的话就显示找到
}
else
{
printf("It hasn't been found!\n");//否则返回0的话就显示没有找到;
goto again;//如果没有找到,就跳到again
}
return 0;
}