本文代码使用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]);