C语言——杨氏矩阵内的查找

杨氏矩阵: 

有一个二维数组. 数组的每行从左到右是递增的,每列从上到下是递增的.

在这样的数组中查找一个数字是否存在。 要求时间复杂度小于O(N);

思路:

 是个矩阵,涉及到每行每列,那么应该用二维数组来解决最适合;要求时间复杂度小于O(n),那说明不能 直接粗暴的用遍历的方法来实现。我们用 要查找的数 与 矩阵的右上角的数 来进行比较,从而进行查找。

可以发现,每一个杨氏矩阵的右上角的数是一个特殊的数,他是所在这一行的最大值,又是所在这一列的最小值。所以我们拿要查找的数(k)和这个右上角数(arr[x][y])进行比较,如果k大于arr[x][y],说明,k不在当前arr[x][y]所在的这一行,因为k比这一行最大的值都大,所以这时候,这一行我们就排除掉了;然后将行数x的值增大1,就是转移到下一行去比较,如果当前的右上角数还是比k小,那么行数继续加一直到右上角数比k大;当右上角数比k大时,说明k就在这一行里,然后将列数y的值减小1,因为一直以来y就是最后一列,将y值一一减小,才能找完这一行的值。 

如下图:

目录

方法一

方法二 


 方法一

代码及详情如下:

#define ROW 3 //列
#define CRO 3 //横

//查找函数
void Find(int arr[CRO][ROW], int k) {
//定义一个ok来表示有没有找到数,找到了将ok变为1
	int ok = 0;

//定义x,y为右上角的数的下标,x为行数,y为列数
	int x = 0;
	int y = ROW-1;

//x行数是从0到CRO-1的,y列数是从ROW-1到0的
	while (x<CRO&&y>=0) {
		if (arr[x][y] > k) {
			y--;
		}
		else if (arr[x][y] < k) {
			x++;
		}
		else {
			printf("找到了,%d在第%d行%d列的位置。\n",k,x+1,y+1);
//找到了该数后,如果后面还有其他和该数相同的数,
//那么要将行数列数都改变,因为该数已经是这一行最大、这一列最小的数了
			x++;
			y--;
			ok = 1;
		}
	}

//如果没有找到,ok就会是0
	if (ok == 0) {
		printf("找不到\n");
	}
}
//主函数
int main() {
//先给二维数组赋值,当为矩阵
	int arr[CRO][ROW] = {
		{1,2,3}, //1,2,3
		{4,5,6}, //2,3,4
		{7,8,9}  //3,4,5
	};
//输入要查找的数
	int k;
	scanf("%d", &k);

	Find(arr, k);

	return 0;
}

 效果如图:


方法二 

上面这种写法可以说是看着很不干净,还有一种写法,就是将Find函数里的逻辑和IO分离,也就是将Find函数里的printf语句分离出来,这样这个函数看着就会干净很多,不仅这个 程序如此,每次写的程序都应该要慢慢养成这个好习惯。

但是我们要输出坐标位置,而返回值又不能同时返回两个值过来,所以我们用指针来完成,用按址传参。

代码如下:

//查找函数
//用指针接收传过来的地址
int FindK(int arr[3][3], int k, int* cro, int* row) {
	int x = 0;//行
	int y = *row - 1;//列

	while (x < *cro && y >= 0) {
		if (arr[x][y] > k)
			y--;
		else if (arr[x][y] < k)
			x++;
		else {
//再找到了的时候,将传过来的行列的值进行修改
			*cro = x+1;
			*row = y+1;
			return 1;
		}
			
	}
	return 0;
}

//主函数
int main() {
	int arr[3][3] = { 
            {1,2,3},
            {2,3,4},
            {3,4,5} };

	int cro = 3;//行
	int row = 3;//列
	int k;//要查找的数
	scanf("%d", &k);
//如果找到了,就返回1
//没有找到就返回0
//将cro和row的地址传过去,那么在函数里面对这两个的值进行了修改就是永久性修改
	if (FindK(arr, k, &cro, &row) == 1) 
		printf("%d 的坐标是(%d,%d)", k, cro, row);
	else
		printf("找不到\n");
	return 0;
}

但是这个函数目前不能像上面那个程序那样,能把所有的k都找出来 ,因为这个程序一旦找到一个k就直接返回了。

如下图:

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

多低调

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值