题目内容
有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数组是否存在。
要求:时间复杂度小于O(N)。
注意:不能采用遍历的方法,遍历的时间复杂度直接就等于O(N)。
解题思路
- 先假设有这样一个3*3的矩阵。
- 矩阵是采用递增的方式进行排序的,每行每列的最末端的数一定是最大的。
1 2 3 ←
4 5 6 ←
7 8 9 ←
↑ ↑ ↑
假设要找的数为k.
-
从右上角开始找,拿 3 和 k 比较
- 如果 3 < k,则说明 3 所在的这一行没有要找的数。小于 k 去掉行。
- 如果 3 > k,则说明 3 所在的这一列没有要找的数。大于 k 去掉列。
-
从左下角开始找,拿 7 和 k 比较
- 如果 7 < k,则说明 7 所在的这一列没有要找的数。小于 k 去掉列。
- 如果 7 > k,则说明 7 所在的这一行没有要找的数。大于 k 去掉行。
代码实现
#include <stdio.h>
#define MAX 3
int Findnum(int arr[MAX][MAX],int k,int* px,int* py)
{
int x = 0; //行
int y = *py -1; //列
while(x <= *px -1 && y >= 0)
{
if(arr[x][y] < k) //排除行
{
x++ ;
}
else if(arr[x][y] > k) //排除列
{
y--;
}
else
{
*px = x; //带回去 x、y 的坐标
*py = y;
return 1;
}
}
return 0; //找不到
}
int main()
{
int arr[MAX][MAX]= {{1,2,3},{4,5,6},{7,8,9}};
int k,x = 3,y = 3;
printf("请输入要查找的数:");
scanf ("%d",&k);
if(1 == Findnum(arr,k,&x,&y))
{
printf("找到了,下标是:%d %d\n",x,y);
}
else
{
printf("没找到\n");
}
return 0;
}
执行结果
请输入要查找的数:3
找到了,下标是:0 2
请输入要查找的数:14
没找到
循环条件
当没找到这个数,而对xy进行调整的时候,要么去掉一行,要么去掉一列,总之就是不停的往左下角7压缩。最后就会导致行自增到最多两行,列自减到最少0列
1 2 3—0
4 5 6—1
7 8 9—2
0 1 2
所以循环条件应该定为x <= *px -1 && y >= 0