剑指Offer刷题——第一天

本文代码使用VS2022开发,采用C语言。由于本人基础比较薄弱,在写代码时未使用伪代码,其中两个Find函数,直接调用,可直接使用:

1.题目描述:

在一个二维数组中(每个一维数组的长度相同),每行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

2.题目解析:

输入:二维数组,目标整数;

问题归类:查找算法

解题思路1——暴力破解

代码如下:

int Find()
{
	//在二维数组arry[3][4]中查找num=32
	int num = 32;
	int arry[3][4] = { {1, 4, 6, 28}, { 2, 7, 32,30}, {10,11,67,79} };

	//一行一行的比较
	for (int row = 0; row < 3; row++)
	{
		for (int col = 0; col < 4; col++)
		{
			if (arry[row][col] == num)
			{
				printf("已找到数据 %d", num);
				break;
			}
		}
	}

	return 0;
}

缺点:在最坏的情况下,需要遍历完所有的元素才能获取结果。如果这个数组的规模是n*m,那么时间复杂度就是O(n x m),没有借助其他的空间,空间复杂度为O(1)。

解题思路2——比较查找法

思想:选定左下角的10(arry[2][0], i=2,j=0)作为起点,如果小于10,则j+1,则下一个数字是11,我们知道32仍比11大,则往右找,继而32比67小,我们应该往上找,找到32。

代码如下:

int Find()
{
	//在二维数组arry[3][4]中查找num=32
	int num = 32;
	int arry[3][4] = { {1, 4, 6, 28}, { 2, 7, 32,30}, {10,11,67,79} };

	for (int i = 2,j = 0; i >= 0 &&i < 3 && j >= 0 && j < 4;)
	{
		if (num == arry[i][j])
		{
			printf("已找到数据 %d", num);
			break;
		}
		if (num > arry[i][j])
		{
			j++;
			continue;
		}
		if (num < arry[i][j])
		{
			i--;
			continue;
		}
		printf("未找到数据 %d", num);
	}

	return 0;
}

复杂度:如果找28,则是最坏的结果,查找直到数组的右上角结束,这样一来,最坏的结果就是O(n + m)。

感悟:在学习这段代码时,for循环用的十分巧妙。for里只使用到了变量初始化、范围约束,将变量自增自减在代码块中使用++,--,continue,break控制,这是我以往未使用到的,可以加以学习。

3.拓展:

本模块是本人在解题时,遇到的一些问题,用于查漏补缺。

花絮1——二维数组传参:

在写代码时,我想实现一个万能的查找函数。函数名Find有两个参数:参数1,二维数组;参数2,待查找数。但是我忽略了二维数组传参规则,以下列三种二维数组传数方式:

方式1:二维数组作为函数的参数

void ArrayTransmit(int array[3][4])

方式2:二维数组参数声明必须指明数组的列数,因为函数调用时传递的是一个指针,它指向由行向量构成的一维数组

void ArrayTransmit(int arry[][4])

方式3:以指针形式传递,指向具有四个元素的一维数组

void ArrayTransmit(int (*arry)[4])

花絮2——计算二维数组的行数、列数

二维数组的元素个数 = 二维数组行数 * 二维数组列数
sizeof(arry[0][0]):一个元素占用的空间
sizeof(arry[0]):一行元素占用的空间
sizeof(arry):整个数组占用的空间

组合到一起:

//计算二维数组总个数
int total = sizeof(arry) / sizeof(arry[0][0]);
 
//计算二维数组的行数
int row = sizeof(arry);

//计算二位数组的列数
int col = sizeof(arry[0]) / sizeof(arry[0][0]);
  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

会敲代码的木木

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

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

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

打赏作者

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

抵扣说明:

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

余额充值