这篇文章的对应思维导图为:思维导图
思维导图对应代码:
//杨氏矩阵
#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);elseprintf("找不到");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");elseprintf("找到了,下标是:%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;
}