[C语言刷题]杨氏矩阵、返回型参数

本文包含知识点

  • 杨氏矩阵极其解法
  • 函数return多个值的四种方法

题目:
杨氏矩阵
有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在。
要求:时间复杂度小于O(N);

  • 一、解题思路
  • 二、代码
    • 2.1第一版——一股脑写在main函数内
    • 2.2第二版——初步封装成函数
    • 2.3第三版——返回型参数(函数内做到return多个值)

一、解题思路

首先我们要清楚什么是杨氏矩阵,题目中也解释得很清楚了,我们看样例
这样的数组有重复元素是允许的,因为题目文的是某个值是否存在,我们只要能找到存在即可,存在多个值没有影响

[C语言刷题]杨氏矩阵、返回型参数_第1张图片

再看要求,时间复杂度要小于O(N),这是什么意思,我相信学过算法的朋友都是一眼便知的。如果你还没有学过,那我就用通俗的话解释一下啊,就是该题不允许我们用二层循环遍历的去寻找某个值,我们要用一种效率比二层循环更高的解法来完成

那这里我们该如何解决呢?
emmmm
我们先联想一下以前学过的二分法查找某个数,这个方法的时间复杂度就是小于O(N)。只不过它针对的是有序的一维数组,这里的杨氏数组是每行每列有序的二维数组
(ps:为什么是小于O(N),就是因为二分法每次判断都会减少一半不满足条件的元素,而不是从小到大一个个的循环求解)

思考片刻之后是不是有点思路了!
接下来我就详细讲讲思路:
    如果我们寻找4是否存在在这个数组中
    首先,我们拿右上角的3和4相比,我们发现3比4小,那么我们把这一整行去掉,为什么?因为每行是递增的,如果这一行最右边的3都比4小了,那么这一行都是比3小的元素,怎么可能存在4
    此时矩阵只有第二行和第三行了,然后我们再看矩阵右上角的6,6比4大,那么我们可以把这一整列去掉,为什么呢,因为列从上往下递增,此时的6是该列最小的值了,最小的6都比4大,那么这一列是不可能存在4了
    就这样一直走下去,直到矩阵的最左下角位置,如果还没有发现4,就说明不存在,反之,则存在
好,接下来看看代码

二、代码

2.1第一版——一股脑写在main函数内

#include

int main()
{
	int arr[3][3] = { 1,2,3,4,5,6,5,7,8 };
	int key = 0;//要寻找的值
	scanf("%d", &key);

	int x = 0;
	int y = 2;//(x,y)是初始矩阵右上角元素的下标
	int flag = 0;
	while (x <= 2 && y >= 0)
	{
		if (arr[x][y] > key)
		{
			y--;//去掉一列
		}
		else if(arr[x][y] < key)
		{
			x++;//去掉一行
		}
		else
		{
			printf("找到了,下标是:(%d,%d)\n", x, y);
			flag = 1;
			break;
		}
	}
	if (0 == flag)
	{
		printf("找不到\n");
	}
	return 0;
}

第一版只能说完成了题目的要求,但我们作为新时代程序猿,对自己的要求要逐步提高,接下来看第二版

2.2第二版——初步封装成函数

这一步其实很简单,把核心功能代码放入函数即可,但是不要心急,这一版是在为第三版做铺垫

#include

void Young_matrix(int arr[3][3], int key, int row, int col)
{
	int x = 0;
	int y = col-1;//(x,y)是初始矩阵右上角元素的下标
	int flag = 0;
	while (x <= row-1 && y >= 0)
	{
		if (arr[x][y] > key)
		{
			y--;//去掉一列
		}
		else if (arr[x][y] < key)
		{
			x++;//去掉一行
		}
		else
		{
			printf("找到了,下标是:(%d,%d)\n", x, y);
			flag = 1;
			break;
		}
	}
	if (0 == flag)
	{
		printf("找不到\n");
	}

}

int main()
{
	int arr[3][3] = { 1,2,3,4,5,6,5,7,8 };
	int key = 0;//要寻找的值
	scanf("%d", &key);
	Young_matrix(arr, key, 3, 3);

	return 0;
}

这样简单粗暴的封装成函数其实是违背函数高内聚低耦合的原则的,这个打印的需求应该交还给用户,函数内最好只负责找到该数的下标,或者返回特定值告诉用户不存在
但是问题又来了,就是如何在函数里返回两个值呢?思考片刻,我们第三版见

2.3第三版——返回型参数(函数内做到return多个值)

首先,我之前写的文章里以及介绍过三种方式能在函数中return多个值,感兴趣的同学可以戳下方链接去看看
一个函数如何实现return好几个返回值

接下来我们介绍第四种方法,就是返回型参数
    这个方法的思想就是,在函数参数中多传入两个变量的地址,然后在函数中解引用访问这两个变量,可以把需要返回的值放入这两个变量,因为是传址,因此可以成功接收到。
    但是,如果这两个参数是毫无意义的,那我觉得不如就用我之前介绍的三种方式。
    但是但是,在杨氏矩阵这道题里面,我们可以让这两个变量具有意义,这就是为什么我会在这篇文章介绍这个方法的原因了
废话不多说,先看代码,然后再介绍这个方法的妙处

#include

void Young_matrix(int arr[3][3], int key, int *px, int *py)
{
	int x = 0;
	int y = *py-1;//(x,y)是初始矩阵右上角元素的下标
	while (x <= *px-1 && y >= 0)
	{
		if (arr[x][y] > key)
		{
			y--;//去掉一列
		}
		else if (arr[x][y] < key)
		{
			x++;//去掉一行
		}
		else
		{
			*px = x;
			*py = y;
			return;
		}
	}
	*px = -1;
	*py = -1;
}

int main()
{
	int arr[3][3] = { 1,2,3,4,5,6,5,7,8 };
	int key = 0;//要寻找的值
	scanf("%d", &key);
	int row = 3;
	int col = 3;
	Young_matrix(arr, key, &row, &col);

	if(-1 == row && -1 == col)
	{
		printf("找不到\n");
	}
	else
	{
		printf("找到了,下标是:(%d,%d)\n", row, col);
	}

	return 0;
}

这个方法,首先就是改进了版本中函数没有满足高内聚低耦合的缺点
其次,我们可以看到函数能够把找到的下标成功返回main函数中
最后,参入的参数是极其有意义的。一、row、col代表矩阵的行列长度,这正是矩阵需要的。二、row、col都有代表下标的属性(意思是行列和下标都是代表位置的变量,用来接收目标下标也是情理之中)

你可能感兴趣的:(c语言,#,刷题,c语言,矩阵,算法)