3G大一下二面题解

发布于:2025-04-11 ⋅ 阅读:(79) ⋅ 点赞:(0)

一、找第一个只出现一次的字符

找第一个只出现一次的字符

描述

给定一个只包含小写字母的字符串,请你找到第一个仅出现一次的字符。如果没有,输出no

投入

一个字符串,长度小于11001100。

输出

输出第一个仅出现一次的字符,若没有则输出no

样本1

投入复制 输出复制
abcabd c

样本2

投入复制 输出复制
aabbcc no
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//__client_id=9c0cba877d6f2f6a67e3ca5ddf999c6a75ca3ad5
//_uid=1107834

int main() {
    char str[1111];
    scanf("%s", str);
    int len = strlen(str);
    int letter[27]={0};
    for (int i = 0; i < len; i++) {
        letter[str[i]-'a']++;
    }
    int find=0;
    for (int i = 0; i < len; i++) {
        for (int j = 0; j < 27; j++) {
            if (letter[str[i]-'a'] == 1) {
                find = 1 ;
                printf("%c", str[i]);
                return 0;
            }
        }
    }
    printf("no");
    return 0;
}

题解

  • int letter[27]={0};:定义一个长度为 27 的整数数组letter,并将其所有元素初始化为 0。这个数组用于统计每个小写字母的出现次数,其中letter[0]对应字母 ‘a’,letter[1]对应字母 ‘b’,依此类推。
  • for (int i = 0; i < len; i++) { letter[str[i]-'a']++; }:遍历字符串str的每个字符,借助str[i]-'a'计算该字符在letter数组中的索引,然后将对应索引位置的元素加 1。
    int find=0;
    for (int i = 0; i < len; i++) {
        for (int j = 0; j < 27; j++) {
            if (letter[str[i]-'a'] == 1) {
                find = 1 ;
                printf("%c", str[i]);
                return 0;
            }
        }
    }
  • int find=0;:定义一个整型变量find,并初始化为 0,用于标记是否找到了只出现一次的字符。
  • 外层for循环for (int i = 0; i < len; i++):遍历字符串str的每个字符。
  • 内层for循环for (int j = 0; j < 27; j++):实际上这个内层循环是多余的,因为只需要检查letter[str[i]-'a']的值是否为 1 即可。
  • if (letter[str[i]-'a'] == 1):若当前字符的出现次数为 1,就将find设为 1,打印该字符,然后返回 0,结束程序。

二、素数回文数的个数

素数回文数的个数

描述

求 1111 到 n之间(包括n),既是素数又是回文数的整数有多少个。

投入

一个大于1111小于1000010000的整数n

输出

1111 到 n之间的素数回文数个数。

样本1

投入复制 输出复制
23 1

暗示

回文数指左右对称的数,如:1111,1212112121。

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//__client_id=9c0cba877d6f2f6a67e3ca5ddf999c6a75ca3ad5
//_uid=1107834

int isPrime(int n) {
    if (n % 2==0||n%3==0) {
        return 0;
    }
    for (int i=5; i<=sqrt(n); i++) {
        if (n%i==0) {
            return 0;
        }
    }
    return 1;
}

int isHuiWen(int n) {
    int arr[12]={0};
    int i=0;//2
    while (n!=0) {
        arr[i++]=n%10;
        n=n/10;
    }
    int l=0,r=i-1;
    while (l<=r) {
        if (arr[l]==arr[r]) {
            l++;
            r--;
        }else{
            return 0;
        }
    }
    return 1;
}

int main() {
    int n;
    scanf("%d",&n);
    int count=1;
    for (int i=12;i<=n;i++) {
        if (isPrime(i)&&isHuiWen(i)) {
            count++;
        }
    }
    printf("%d",count);
    return 0;
}

题解

  • 该函数用于判断一个整数 n 是否为质数。
  • 首先检查 n 是否能被 2 或 3 整除,如果能,则 n 不是质数,返回 0。
  • 然后从 5 开始,以 6 为步长,检查 n 是否能被小于等于其平方根的数整除,如果能,则 n 不是质数,返回 0。
  • 如果都不满足上述条件,则 n 是质数,返回 1。
  • 该函数用于判断一个整数 n 是否为回文数。
  • 首先将 n 的每一位数字存储在数组 arr 中。
  • 然后使用双指针法,从数组的两端向中间遍历,如果对应位置的数字不相等,则 n 不是回文数,返回 0。
  • 如果所有对应位置的数字都相等,则 n 是回文数,返回 1。

三、基因相关性

基因相关性

描述

为了获知基因序列在功能和结构上的相似性,经常需要将几条不同序列的脱氧核糖核酸进行比对,以判断该比对的脱氧核糖核酸是否具有相关性。

现比对两条长度相同的脱氧核糖核酸序列。首先定义两条脱氧核糖核酸序列相同位置的碱基为一个碱基对,如果一个碱基对中的两个碱基相同的话,则称为相同碱基对。接着计算相同碱基对占总碱基对数量的比例,如果该比例大于等于给定阈值时则判定该两条脱氧核糖核酸序列是相关的,否则不相关。

投入

有三行,第一行是用来判定出两条脱氧核糖核酸序列是否相关的阈值,随后22行是两条脱氧核糖核酸序列(长度不大于500500)。

输出

若两条脱氧核糖核酸序列相关,则输出yes,否则输出no

样本1

投入复制 输出复制
0.85 ATCGCCGTAAGTAACGGTTTTAAATAGGCC ATCGCCGGAAGTAACGGTCTTAAATAGGCC yes
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//__client_id=9c0cba877d6f2f6a67e3ca5ddf999c6a75ca3ad5
//_uid=1107834

int main() {
    double n;
    scanf("%lf", &n);
    char str1[501];
    char str2[501];
    scanf("%s", str1);
    scanf("%s", str2);
    int len = strlen(str1);
    int sameLen=0;
    for (int i = 0; i < len; i++) {
        if (str1[i] == str2[i]) {
            sameLen++;
        }
    }
    double k = (double) sameLen / (double) len;
    if (k>n) {
        printf("yes\n");
    }else {
        printf("no\n");
    }
    return 0;
}

题解

  • 定义了一个双精度浮点型变量n,用来存储用户输入的相似度阈值。
  • 借助scanf函数从标准输入读取一个双精度浮点数,并把它存储到变量n中。
  • 定义了两个字符数组str1str2,长度均为 501,用于存储用户输入的两个字符串。
  • 利用scanf函数从标准输入读取两个字符串,并分别存到str1str2中。
  • 运用strlen函数计算str1的长度,并将其存储在变量len中。
  • 定义一个整型变量sameLen,初始化为 0,用于统计两个字符串中相同位置上相同字符的数量。
  • 通过for循环遍历两个字符串的每个字符,若对应位置的字符相同,则sameLen加 1。
  • sameLenlen强制转换为双精度浮点型,然后相除得到相似度k
  • kn进行比较,若k大于n,则输出yes;否则,输出no

四、欢乐的跳

欢乐的跳

描述

一个n个元素的整数数组,如果数组两个连续元素之间差的绝对值包括了[1,n−1]之间的所有整数,则称之符合"欢乐的跳",如数组{1,4,2,3}{1,4,2,3}符合"欢乐的跳",因为差的绝对值分别为:3,2,13,2,1。

给定一个数组,你的任务是判断该数组是否符合"欢乐的跳"。

投入

每组测试数据第一行以一个整数n(1≤n≤1000)开始,接下来n个空格隔开的在[−108,108][−108,108]之间的整数。

输出

对于每组测试数据,输出一行若该数组符合"欢乐的跳"则输出Jolly,否则输出Not jolly

样本1

投入复制 输出复制
4 1 4 2 3 Jolly

样本2

投入复制 输出复制
5 1 4 2 -1 6 Not jolly

暗示

1≤n≤1000

#include <stdio.h>
int main() {
	int n, arr[1000] = { 0 }, chazhi[1000] = { 1 };
	scanf("%d", &n);
	int i, j, cha;
	for (i = 1; i < n; i++) {
		chazhi[i]++;
	}
	for (i = 0; i < n; i++) {
		scanf("%d", &arr[i]);
	}
	for (i = 0; i < n - 1; i++) {
		if (arr[i] > arr[i + 1])
			 cha = arr[i] - arr[i + 1];
		else
			 cha = arr[i + 1] - arr[i];
		for (j = 0; j < n - 1; j++) {
			if (cha == chazhi[j]) {
				chazhi[j] = 0;
			}
		}
	}
	for (i = 0; i < n - 1; i++) {
		if (chazhi[i] != 0) {
			printf("Not jolly");
			return 0;
		}
		if (i == n - 2 && chazhi[i] == 0) {
			printf("Jolly");
			return 0;
		}
	}
	return 0;
}

题解

  • chazhi 数组从索引 1 到 n - 1 的元素值都加 1,使得 chazhi 数组元素从 1 到 n - 1 初始值为 1 到 n - 1,后续用于标记差值是否出现。
  • 通过 scanf 函数从标准输入读取 n 个整数,并将它们依次存储到数组 arr 中。
  • 外层 for 循环遍历数组 arr 中除最后一个元素外的每个元素。
  • 对于每对相邻元素 arr[i]arr[i + 1],计算它们差值的绝对值并存储在 cha 中。
  • 内层 for 循环遍历 chazhi 数组,如果 cha 的值与 chazhi[j] 相等,则将 chazhi[j] 置为 0,表示该差值已经出现过。
  • 遍历 chazhi 数组,如果发现某个元素不为 0,说明从 1 到 n - 1 中有差值未出现,该序列不是欢乐序列,输出 Not jolly 并结束程序。
  • 当遍历到 i 等于 n - 2chazhi[i] 为 0 时,说明从 1 到 n - 1 的所有差值都出现过,该序列是欢乐序列,输出 Jolly 并结束程序。

五、开关灯

开关灯

描述

假设有N盏灯(N为不大于50005000的正整数),从11 到 N按顺序依次编号,初始时全部处于开启状态;第一个人(11号)将灯全部关闭,第二个人(22号)将编号为22的倍数的灯打开,第三个人(33号)将编号为33的倍数的灯做相反处理(即,将打开的灯关闭,将关闭的灯打开)。依照编号递增顺序,以后的人都和33号一样,将凡是自己编号倍数的灯做相反处理。问当第N个人操作完之后,有哪些灯是关闭着的?

投入

输入为一行,一个整数N,为灯的数量。

输出

输出为一行,按顺序输出关着的灯的编号。编号与编号之间间隔一个空格。

样本1

投入复制 输出复制
10 1 4 9

样本2

投入复制 输出复制
5 1 4
#include <stdio.h>

#define MAX_N 5001

int main() {
    int n;
    // 读取输入的灯的数量
    scanf("%d", &n);

    // 初始化所有灯为开启状态,0 表示关闭,1 表示开启
    int lights[MAX_N] = {0};
    for (int i = 1; i <= n; i++) {
        lights[i] = 1;
    }

    // 模拟每个人对灯的操作
    for (int person = 1; person <= n; person++) {
        for (int light = person; light <= n; light += person) {
            lights[light] = 1 - lights[light];
        }
    }

    // 输出关闭的灯的编号
    int first = 1;
    for (int i = 1; i <= n; i++) {
        if (lights[i] == 0) {
            if (!first) {
                printf(" ");
            }
            printf("%d", i);
            first = 0;
        }
    }
    printf("\n");

    return 0;
}    

题解

  • 定义一个长度为 MAX_N 的整型数组 lights,用于存储每盏灯的状态。
  • 通过循环将数组中索引从 1 到 n 的元素初始化为 1,表示所有灯初始状态为开启。
  • 外层循环 for (int person = 1; person <= n; person++):遍历每个人,从第 1 个人到第 n 个人。
  • 内层循环 for (int light = person; light <= n; light += person):对于第 person 个人,将编号为 person 的倍数的灯的状态进行切换。通过 lights[light] = 1 - lights[light]; 实现状态切换,若原来为 1(开启)则变为 0(关闭),若原来为 0 则变为 1。
  • 定义一个变量 first 用于标记是否是第一个输出的关闭灯的编号。
  • 遍历数组 lights,如果某盏灯的状态为 0(关闭),则输出其编号。若不是第一个输出的编号,则先输出一个空格进行分隔。
  • 最后输出一个换行符。

六、二进制分类

二进制分类

描述

若将一个正整数化为二进制数,在此二进制数中,我们将数字11的个数多于数字00的个数的这类二进制数称为A类数,否则就称其为B类数。

例如:

(13)10=(1101)2(13)10=(1101)2,其中11的个数为33,00的个数为11,则称此数为A类数;

(10)10=(1010)2(10)10=(1010)2,其中11的个数为22,00的个数也为22,称此数为B类数;

(24)10=(11000)2(24)10=(11000)2,其中11的个数为22,00的个数为33,则称此数为B类数;

程序要求:求出1~n之中(1≤n≤1000),全部A,B两类数的个数。

投入

输入n。

输出

一行,包含两个整数,分别是A类数和B类数的个数,中间用单个空格隔开。

样本1

投入复制 输出复制
7 5 2
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    int n;
    scanf("%d",&n);
    int aC=0;
    int bC=0;
    for(int i=1;i<=n;i++) {
        int temp=i;
        int oneC=0,zeroC=0;
        while (temp!=0) {
            if (temp%2) {
                oneC++;
            }else {
                zeroC++;
            }
            temp=temp/2;
        }
        if (oneC>zeroC) {
            aC++;
        }else {
            bC++;
        }
    }
    printf("%d %d",aC,bC);
    return 0;
}

题解

  • 定义两个整型变量aCbC,分别用于统计二进制表示中 1 的个数大于 0 的个数的数的数量,以及 1 的个数小于等于 0 的个数的数的数量,并初始化为 0。
  • 外层for循环for(int i=1;i<=n;i++):遍历从 1 到n的每一个整数。
  • 对于每个整数i,将其赋值给temp,并初始化oneC(用于统计二进制表示中 1 的个数)和zeroC(用于统计二进制表示中 0 的个数)为 0。
  • 内层while循环while (temp!=0):通过不断对temp取余 2 并除以 2,来获取temp的二进制表示中的每一位。如果取余结果为 1,则oneC加 1;如果为 0,则zeroC加 1。
  • 循环结束后,根据oneCzeroC的大小关系,更新aCbC的值。

七、T2 点亮灯笼

T2 点亮灯笼

描述

有 n个灯笼环形摆放。最开始,这些灯笼都是关闭的状态。

操作台上有n个按钮,按下第x个按钮时,会反转灯笼x以及相邻两个灯笼的状态。「反转」是指关闭变成点亮、点亮变成关闭。

举一个例子:如果按下第55个按钮,则44、55、66号灯笼都会反转;如果按下第n个按钮,则n−1,n,1这三个灯笼状态反转。这是因为灯笼放置为环形,n−1是与n相邻的灯笼。

我们依次按下了一些按钮。你需要编程求出当我们的操作完成后,最终这些灯笼的状态。

投入

第一行,两个正整数n*,m,分别表示共有n个灯笼、我们按了m*次按钮。

接下来m行,每行一个正整数,表示我们在那一次操作中按下了哪个按钮。

输出

仅一行,n个整数,依次表示n个灯笼的状态,用空格隔开。以0代表灯笼关闭,以1代表灯笼点亮。

样本1

投入复制 输出复制
5 4 1 3 1 2 1 0 0 1 0

暗示

样例解释

灯笼序列的状态如下:

0 0 0 0 0  # 初始状态
1 1 0 0 1  # 按下 1 之后的状态
1 0 1 1 1  # 按下 3 之后的状态
0 1 1 1 0  # 按下 1 之后的状态
1 0 0 1 0  # 按下 2 之后的状态

复制

纯文本

因此你应当输出1 0 0 1 0

数据规模与约定

对于100%的数据,有n≤1000,m≤1000。

#include <stdio.h>

#define MAX_N 1001

// 反转灯笼状态的函数
void toggleLights(int lights[], int n, int button) {
    // 处理前一个灯笼
    int prev = (button - 1 - 1 + n) % n + 1;
    lights[prev] = 1 - lights[prev];

    // 处理当前按下按钮对应的灯笼
    lights[button] = 1 - lights[button];

    // 处理后一个灯笼
    int next = (button - 1 + 1) % n + 1;
    lights[next] = 1 - lights[next];
}

int main() {
    int n, m;
    // 读取灯笼数量和操作次数
    scanf("%d %d", &n, &m);

    // 初始化所有灯笼为关闭状态
    int lights[MAX_N] = {0};

    for (int i = 0; i < m; i++) {
        int button;
        // 读取每次按下的按钮编号
        scanf("%d", &button);
        // 调用反转函数
        toggleLights(lights, n, button);
    }

    // 输出最终的灯笼状态
    for (int i = 1; i <= n; i++) {
        if (i > 1) {
            printf(" ");
        }
        printf("%d", lights[i]);
    }
    printf("\n");

    return 0;
}    

题解

  1. toggleLights函数
// 反转灯笼状态的函数
void toggleLights(int lights[], int n, int button) {
    // 处理前一个灯笼
    int prev = (button - 1 - 1 + n) % n + 1;
    lights[prev] = 1 - lights[prev];

    // 处理当前按下按钮对应的灯笼
    lights[button] = 1 - lights[button];

    // 处理后一个灯笼
    int next = (button - 1 + 1) % n + 1;
    lights[next] = 1 - lights[next];
}
  • 该函数的功能是反转指定按钮对应的灯笼及其相邻两个灯笼的状态。
  • prev:借助取模运算算出前一个灯笼的编号,以此处理环形结构。
  • next:同样利用取模运算算出后一个灯笼的编号,以应对环形结构。
  • 通过lights[prev] = 1 - lights[prev];等语句反转灯笼状态。
  1. main函数
int main() {
    int n, m;
    // 读取灯笼数量和操作次数
    scanf("%d %d", &n, &m);

    // 初始化所有灯笼为关闭状态
    int lights[MAX_N] = {0};

    for (int i = 0; i < m; i++) {
        int button;
        // 读取每次按下的按钮编号
        scanf("%d", &button);
        // 调用反转函数
        toggleLights(lights, n, button);
    }

    // 输出最终的灯笼状态
    for (int i = 1; i <= n; i++) {
        if (i > 1) {
            printf(" ");
        }
        printf("%d", lights[i]);
    }
    printf("\n");

    return 0;
}
  • 读取灯笼数量n和操作次数m
  • 把所有灯笼的初始状态设为关闭(lights[MAX_N] = {0};)。
  • 循环m次,每次读取按下的按钮编号,然后调用toggleLights函数反转对应灯笼的状态。
  • 最后输出所有灯笼的最终状态,状态之间用空格分隔。

八、查找

查找

描述

输入n个不超过109109的单调不减的(就是后面的数字不小于前面的数字)非负整数1,2,…,a1,a2,…,an,然后进行m次询问。对于每次询问,给出一个整数q,要求输出这个数字在序列中第一次出现的编号,如果没有找到的话输出−1 。

投入

第一行22个整数nm,表示数字个数和询问次数。

第二行n个整数,表示这些待查询的数字。

第三行m个整数,表示询问这些数字的编号,从11开始编号。

输出

输出一行,m个整数,以空格隔开,表示答案。

样本1

投入复制 输出复制
11 3 1 3 3 3 5 7 9 11 13 15 15 1 3 6 1 2 -1

暗示

数据保证,1≤n≤10^6 ,0≤ai,q≤10^9, 1≤m≤10^5

本题输入输出量较大,请使用较快的超正析象管(Image Orthicon)方式。

int binarySearch(int nums[], int n, int target) {
	int left = 1, right = n , result = -1;

	while (left <= right) {
		int middle = left + (right - left) / 2;

		if (nums[middle] == target) {
			result = middle;
			right = middle - 1;  
		}
		else if (nums[middle] < target) {
			left = middle + 1;
		}
		else {
			right = middle - 1;
		}
	}
	return (result == -1) ? -1 : result;
}
#include<stdio.h>
int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	int nums[1000000], search[100000];
	for (int i = 1; i <= n; i++) {
		scanf("%d", &nums[i]);
	}
	for (int j = 0; j < m; j++) {
		scanf("%d", &search[j]);
	}

	for (int i = 0; i < m; i++) {
		int result = binarySearch(nums, n, search[i]);
		printf("%d ", result);
	}
	return 0;
}

题解

  1. binarySearch函数
int binarySearch(int nums[], int n, int target) {
    int left = 1, right = n , result = -1;

    while (left <= right) {
        int middle = left + (right - left) / 2;

        if (nums[middle] == target) {
            result = middle;
            right = middle - 1;  
        }
        else if (nums[middle] < target) {
            left = middle + 1;
        }
        else {
            right = middle - 1;
        }
    }
    return (result == -1) ? -1 : result;
}
  • 变量初始化:
    • left初始化为 1,right初始化为n,这表明数组下标从 1 开始。
    • result初始化为 -1,用于存储目标值首次出现的位置,若未找到则保持 -1。
  • 二分查找过程:
    • while (left <= right):只要左边界不超过右边界,就继续查找。
    • int middle = left + (right - left) / 2;:计算中间位置,避免整数溢出。
    • if (nums[middle] == target):若中间元素等于目标值,更新result为中间位置,并将右边界right更新为middle - 1,继续向左查找可能的更早出现的目标值。
    • else if (nums[middle] < target):若中间元素小于目标值,将左边界left更新为middle + 1,在右半部分继续查找。
    • else:若中间元素大于目标值,将右边界right更新为middle - 1,在左半部分继续查找。
  • 返回结果:最终返回result
  1. main函数
#include<stdio.h>
int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    int nums[1000000], search[100000];
    for (int i = 1; i <= n; i++) {
        scanf("%d", &nums[i]);
    }
    for (int j = 0; j < m; j++) {
        scanf("%d", &search[j]);
    }

    for (int i = 0; i < m; i++) {
        int result = binarySearch(nums, n, search[i]);
        printf("%d ", result);
    }
    return 0;
}
  • 输入读取:

    • scanf("%d%d", &n, &m);:读取数组的长度n和要查找的元素数量m
    • int nums[1000000], search[100000];:定义两个数组,nums用于存储有序数组,search用于存储要查找的目标元素。
    • for (int i = 1; i <= n; i++) { scanf("%d", &nums[i]); }:读取有序数组的元素,注意数组下标从 1 开始。
    • for (int j = 0; j < m; j++) { scanf("%d", &search[j]); }:读取要查找的目标元素。
  • 查找并输出结果:

    • for (int i = 0; i < m; i++) { int result = binarySearch(nums, n, search[i]); printf("%d ", result); }:对每个目标元素调用binarySearch函数进行查找,并输出结果。

九、排队接水

排队接水

描述

n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小。

投入

第一行为一个整数n

第二行n个整数,第i个整数Ti表示第i个人的接水时间T**i

输出

输出文件有两行,第一行为一种平均时间最短的排队顺序;第二行为这种排列方案下的平均等待时间(输出结果精确到小数点后两位)。

样本1

投入复制 输出复制
10 56 12 1 99 1000 234 33 55 99 812 3 2 7 8 1 4 9 6 10 5 291.90

暗示

1≤n≤1000,1≤ti≤10^6 ,不保证ti不重复。

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include <stdio.h>
#include <stdlib.h>

// 定义结构体来存储每个人的编号和接水时间
typedef struct {
    int id;
    int time;
} Person;

// 比较函数,用于 qsort 排序
int compare(const void* a, const void* b) {
    Person* p1 = (Person*)a;
    Person* p2 = (Person*)b;
    return p1->time - p2->time;
}

int main() {
    int n;
    // 读取人数
    scanf("%d", &n);

    Person people[1001];
    for (int i = 0; i < n; i++) {
        people[i].id = i + 1;
        // 读取每个人的接水时间
        scanf("%d", &people[i].time);
    }

    // 按照接水时间从小到大排序
    qsort(people, n, sizeof(Person), compare);

    // 输出排队顺序
    for (int i = 0; i < n; i++) {
        printf("%d", people[i].id);
        if (i < n - 1) {
            printf(" ");
        }
    }
    printf("\n");

    long long total_waiting_time = 0;
    long long current_waiting_time = 0;
    for (int i = 0; i < n; i++) {
        total_waiting_time += current_waiting_time;
        current_waiting_time += people[i].time;
    }

    // 计算平均等待时间
    double average_waiting_time = (double)total_waiting_time / n;
    // 输出平均等待时间,精确到小数点后两位
    printf("%.2f\n", average_waiting_time);

    return 0;
}

题解

  • 结构体定义
// 定义结构体来存储每个人的编号和接水时间
typedef struct {
    int id;
    int time;
} Person;

定义了一个名为Person的结构体,包含两个成员:id表示人的编号,time表示接水所需的时间。

  • 比较函数
// 比较函数,用于 qsort 排序
int compare(const void* a, const void* b) {
    Person* p1 = (Person*)a;
    Person* p2 = (Person*)b;
    return p1->time - p2->time;
}

定义了一个比较函数compare,用于qsort函数对Person结构体数组进行排序。比较函数根据接水时间time的大小进行比较,返回值小于 0 表示p1的接水时间小于p2的接水时间,返回值大于 0 表示p1的接水时间大于p2的接水时间,返回值等于 0 表示两者接水时间相等。

  • 主函数main
    • 读取排队的人数n
    • 定义一个Person结构体数组people,大小为 1001(可以容纳最多 1001 个人)。
    • 通过循环读取每个人的接水时间,并为每个人分配编号(从 1 开始)。
    • 使用qsort函数对people数组进行排序,排序依据是接水时间time
    • 输出排队顺序,即每个人的编号。
    • 计算所有人的总等待时间,通过累加每个人前面的人的接水时间来计算。
    • 计算平均等待时间,将总等待时间除以人数n,并输出结果,保留两位小数。

网站公告

今日签到

点亮在社区的每一天
去签到