这篇文章的对应思维导图为:思维导图
思维导图对应代码:
//杨氏矩阵
#include<stdio.h>
//void ysjz1(int a[3][3],int k) {
// int x = 0;
// int y = 2;
// while (x <= 2 && y >= 0) {
// if (a[x][y] > k) {
// y--;
// }
// else if (a[x][y] < k) {
// x++;
// }
// else {
// printf("%d %d", x, y);
// return ;
// }
// }
// printf("找不到");
//}
//void ysjz2(int(*a)[3], int k) {
// int x = 0;
// int y = 2;
// while (x <= 2 && y >= 0) {
// if (a[x][y] > k) {
// y--;
// }
// else if (a[x][y] < k) {
// x++;
// }
// else {
// printf("%d %d", x, y);
// return ;
// }
// }
// printf("找不到");
//}
//int ysjz3(int(*a)[3],int k,int* px,int* py) {
// int x = 0;
// int y = *py-1;
//
// while (x <= (*px - 1) && y >= 0) {
// if (a[x][y] > k) {
// y--;
// }
// else if (a[x][y] < k) {
// x++;
// }
// else {
// //printf("%d %d", x, y);
// *px = x;
// *py = y;
// return 1;
// }
// }
// //printf("找不到");
// return 0;
//}
int main() {
int a[3][3] = { 1,2,3,4,5,6,7,8,9 };
//1 2 3
//4 5 6
//7 8 9
//元素3在第0行第2列
int x = 3;
int y = 3;
int k = 0;
scanf_s("%d", &k);
//ysjz1(a, k);
//ysjz2(a, k);
if(ysjz3(a, k, &x, &y))
printf("%d %d", x, y);
else
printf("找不到");
return 0;
}
题目描述:
有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在。要求:时间复杂度小于O(N);
对于杨氏矩阵而言,右上角和左下角的元素是有特点的。右上角的元素是一行中最大的,一列中最小的。左下角的元素是一行中最小的,是一列中最大的。所以我们可以从右上角或者左下角开始查找。比如:从右上角开始查找的时候,右上角的元素比我们要查找元素小,我们就可以去掉右上角元素所在的这一行;右上角的元素比我们要查找的元素大,我们就可以去掉右上角元素所在的这一列。然后依然找右上角的元素继续和要查找的元素与比较。这样每一次比较去掉一行或者去掉一列。这个查找效率是高于遍历数组元素的,所以时间复杂度是小于O(N),也满足题目要求。
问题解决:
1 2 3
4 5 6
7 8 9
3是第一行的最大值,也是第三列的最小值。将要查找的数字和3比较,如果比3大就加到下一行,如果比3小就减到前一列,但是,行和列有范围,当在这个范围内还没有找到就打印找不到。
#include<stdio.h>
int main()
{
int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
int k = 0;
scanf_s("%d", &k);
//在VS2019中使用了scanf_s,其实和scanf一样的作用
int x = 0;
int y = 2;
//初始化为3所在的位置
int flag = 0;
while (x<=2 && y>=0)
{
if (arr[x][y] < k)
{
x++;
//行数加一
}
else if (arr[x][y] > k)
{
y--;
//列数减一
}
else
{
printf("找到了,下标是:%d %d\n", x, y);
flag = 1;
//找到之后就记录对应下标并且将标志设置为1然后推出循环
break;
}
}
if (flag == 0)
printf("找不到\n");
return 0;
}
封装为函数并且带回返回值:
#include<stdio.h>
void young_tableau_search(int arr[3][3], int k, int *px, int *py)
{
int x = 0;
int y = *py-1;
int flag = 0;
while (x <= *px-1 && y >= 0)
{
if (arr[x][y] < k)
{
x++;
}
else if (arr[x][y] > k)
{
y--;
}
else
{
*px = x;
*py = y;
return;
}
}
*px = -1;
*py = -1;
}
int main()
{
int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
int k = 0;
scanf_s("%d", &k);
int x = 3;
int y = 3;
young_tableau_search(arr, k, &x, &y);
if (x == -1 && y == -1)
printf("找不到\n");
else
printf("找到了,下标是:%d %d\n", x, y);
return 0;
}
#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;
}
}
return 0;
}
int main()
{
int a[][3] = { {1, 3, 5},
{3, 5, 7},
{5, 7, 9} };
if (findnum(a, 3, 3, 2))
{
printf("It has been found!\n");
}
else
{
printf("It hasn't been found!\n");
}
return 0;
}