前言:
此时朋友们对“c语言中23是什么意思”大概比较着重,姐妹们都想要了解一些“c语言中23是什么意思”的相关知识。那么小编也在网络上网罗了一些有关“c语言中23是什么意思””的相关内容,希望我们能喜欢,大家一起来了解一下吧!学习工控知识,就来工控小新
农历十一月十一日 2023/12/ 24
往期推荐
2023年12月23日,每天花费一分钟练习C语言:用C语言写出杨辉三角的第n行,只需4个步骤!
2023年12月22日,每天花费一分钟练习C语言:十万以内阶乘和数的秘密,只有5个数字知道!
每日一练
/ Daily Exercises
题目:
给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值,如果给出数组元素个数小于2,则返回0
题目分析
这个题目的难点在于如何在不实际排序数组的情况下,快速地找出最大的差值。如果我们直接对数组进行排序,那么时间复杂度至少是 ( log)O(nlogn),其中 n是数组的长度。这样的算法可能会超时,或者浪费不必要的时间。
我们可以利用一个数学的性质,即抽屉原理,来简化这个问题。抽屉原理的一个简单的表述是:如果有n+1个苹果放在 n个抽屉里,那么至少有一个抽屉里有两个或以上的苹果。换句话说,如果有多于抽屉数量的物品,那么必然有一个抽屉里有多于一个的物品。
那么,这个性质和我们的题目有什么关系呢?
我们可以把数组的元素看作是苹果,把一些区间看作是抽屉。
具体地,我们先找出数组中的最大值和最小值,然后将它们之间的区间分成 n−1个等长的子区间,每个子区间就是一个抽屉。然后,我们遍历数组,把每个元素放到对应的子区间里,也就是对应的抽屉里。这样,我们就可以得到一个分布情况,有些抽屉里有多个元素,有些抽屉里没有元素,有些抽屉里只有一个元素。
根据抽屉原理,我们可以知道,如果有一个抽屉里没有元素,那么必然有另一个抽屉里有两个或以上的元素。这意味着,如果我们从左到右扫描这些抽屉,那么每当我们遇到一个空抽屉,我们就可以确定,这个空抽屉的左边的抽屉里有元素,而且这个元素是这个抽屉里的最大值;这个空抽屉的右边的抽屉里也有元素,而且这个元素是这个抽屉里的最小值。那么,这两个元素之间的差值,就是一个候选的最大差值。我们只需要记录下这些候选的最大差值,然后从中选出最大的一个,就是我们要求的答案。
这个算法的时间复杂度是 O(n),因为我们只需要遍历一次数组,然后扫描一次抽屉。空间复杂度也是 O(n),因为我们需要存储每个抽屉的最大值和最小值。
程序展示
根据上面的分析,我们可以用C语言来实现这个算法。我们首先定义一个结构体,用来表示每个抽屉的信息,包括是否有元素,最大值和最小值。然后,我们定义一个函数,用来计算给定数组的最大差值。函数的主要步骤如下:
1、初始化一个长度为n−1的结构体数组,用来表示n−1个抽屉,每个抽屉的信息都设为初始值,即没有元素,最大值和最小值都为0。2、遍历数组,找出最大值和最小值,以及每个元素对应的抽屉的下标。把每个元素放到对应的抽屉里,更新抽屉的信息,即是否有元素,最大值和最小值。3、扫描抽屉,记录下每个空抽屉的左右两边的元素的差值,作为候选的最大差值。从中选出最大的一个,作为最终的答案。4、如果数组的长度小于2,或者最大值和最小值相等,那么返回0,表示没有差值。
#include <stdio.h>#include <stdlib.h>#include <time.h>// 定义一个结构体,用来表示每个抽屉的信息typedef struct bucket { int has_element; // 是否有元素 int max; // 最大值 int min; // 最小值} bucket;// 定义一个函数,用来比较两个整数的大小,用于排序int compare(const void* a, const void* b) { return *(int*)a - *(int*)b;}// 定义一个函数,用来生成一个长度为n的随机数组,返回数组的指针int* generate_random_array(int n) { int* arr = (int*)malloc(sizeof(int) * n); // 分配内存空间 for (int i = 0; i < n; i++) { arr[i] = rand() % 100; // 生成0到99之间的随机整数 } return arr;}// 定义一个函数,用来打印一个数组,方便查看void print_array(int* arr, int n) { printf("["); for (int i = 0; i < n; i++) { printf("%d", arr[i]); if (i < n - 1) printf(", "); } printf("]\n");}// 定义一个函数,用来计算给定数组的最大差值int max_gap(int* arr, int n) { // 如果数组的长度小于2,或者数组中的元素都相等,那么返回0 if (n < 2) return 0; int max = arr[0], min = arr[0]; for (int i = 1; i < n; i++) { if (arr[i] > max) max = arr[i]; if (arr[i] < min) min = arr[i]; } if (max == min) return 0; // 初始化一个长度为n-1的结构体数组,用来表示n-1个抽屉 bucket* buckets = (bucket*)malloc(sizeof(bucket) * (n - 1)); for (int j = 0; j < n - 1; j++) { buckets[j].has_element = 0; buckets[j].max = 0; buckets[j].min = 0; } // 遍历数组,找出每个元素对应的抽屉的下标,把元素放到对应的抽屉里,更新抽屉的信息 int gap = max - min; // 数组的最大值和最小值的差值 int bucket_size = gap / (n - 1); // 每个抽屉的大小 if (bucket_size == 0) bucket_size = 1; // 防止除数为0的情况 for (int k = 0; k < n; k++) { int index = (arr[k] - min) / bucket_size; // 计算元素对应的抽屉的下标 if (index >= n - 1) index = n - 2; // 防止下标越界的情况 if (buckets[index].has_element == 0) { // 如果抽屉里没有元素,那么把元素设为最大值和最小值 buckets[index].has_element = 1; buckets[index].max = arr[k]; buckets[index].min = arr[k]; } else { // 如果抽屉里有元素,那么更新最大值和最小值 if (arr[k] > buckets[index].max) buckets[index].max = arr[k]; if (arr[k] < buckets[index].min) buckets[index].min = arr[k]; } } // 扫描抽屉,记录下每个空抽屉的左右两边的元素的差值,作为候选的最大差值 int max_gap = 0; // 最大差值 int prev = min; // 前一个非空抽屉的最大值,初始为数组的最小值 for (int m = 0; m < n - 1; m++) { if (buckets[m].has_element == 0) continue; // 如果抽屉为空,跳过 int curr = buckets[m].min; // 当前非空抽屉的最小值 int curr_gap = curr - prev; // 当前差值 if (curr_gap > max_gap) max_gap = curr_gap; // 更新最大差值 prev = buckets[m].max; // 更新前一个非空抽屉的最大值 } // 释放内存空间 free(buckets); // 返回最大差值 return max_gap;}// 定义一个函数,用来测试我们的函数是否正确void test(int n) { // 生成一个长度为n的随机数组 int* arr = generate_random_array(n); // 打印数组 printf("The original array is: "); print_array(arr, n); // 对数组进行排序 qsort(arr, n, sizeof(int), compare); // 打印排序后的数组 printf("The sorted array is: "); print_array(arr, n); // 计算相邻元素之间的最大差值,作为期望的答案 int expected = 0; for (int i = 1; i < n; i++) { int curr = arr[i] - arr[i - 1]; if (curr > expected) expected = curr; } // 调用我们的函数,计算数组的最大差值,作为实际的答案 int actual = max_gap(arr, n); // 比较期望的答案和实际的答案是否相等 printf("The expected answer is: %d\n", expected); printf("The actual answer is: %d\n", actual); if (expected == actual) { printf("Correct!\n"); } else { printf("Wrong!\n"); } // 释放内存空间 free(arr);}// 定义主函数,用来运行测试int main() { // 设置随机数种子 srand(time(NULL)); // 测试10次 for (int i = 0; i < 10; i++) { printf("Test %d:\n", i + 1); // 随机生成一个长度为1到10之间的正整数 int n = rand() % 10 + 1; // 调用测试函数 test(n); printf("\n"); } return 0;}
程序测试
为了验证我们的程序是否正确,我们可以用一些测试用例来检验。我们可以用以下的方法来生成测试用例:
随机生成一个长度为n的数组,其中n是一个随机的正整数,数组的元素是随机的整数。对数组进行排序,然后计算相邻元素之间的最大差值,作为期望的答案。调用我们的函数,计算数组的最大差值,作为实际的答案。比较期望的答案和实际的答案是否相等,如果相等,说明我们的函数正确,如果不相等,说明我们的函数有误。
源代码获取
#软件下载通道#
我用夸克网盘分享了「20231224」,点击链接即可保存。打开「夸克APP」,无需下载在线播放视频,畅享原画5倍速,支持电视投屏。
链接:
(链接和提取码建议复制粘贴,手动输入容易出现错误)
#支持一下#
分享整理,测试发布不易 如果您方便的话可以帮忙点一下↓↓
谢谢大家!
下期题目
重复的DNA序列
所有DNA都由一系列缩写为A',C,G'和·T的核昔酸组成,例如:ACGAATTCCG"。在研究DNA 时,识别DNA中的重复序列有时会对研究非常有帮助。编写一个函数来找出所有目标子串,目标子串的长度为10,且在 DNA 字符串s 中出现次数超过一次。
点赞加关注,学习不迷路
微信公众号|工控小新
学习工控知识就来工控小新,为你提供工控笔记知识:EPLAN电气绘图 | TIA博图基础 | CAD | C语言教学 | 单片机基础 | 三菱PLC ... 每日持续更新中
#头条创作挑战赛#
标签: #c语言中23是什么意思 #c语言求3个数的最大值函数是多少 #c 字符串比较大小 #c语言求最小值及其最大下标