实验室二面题解

实验室二面题解

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

[B2110 找第一个只出现一次的字符 - 洛谷]

题目描述

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

输入格式

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

输出格式

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

输入输出样例 #1
输入 #1
abcabd
输出 #1
c
输入输出样例 #2
输入 #2
aabbcc
输出 #2
no
考查知识点

字符串

解题思路
  • 将字符串存入str中,定义数组count用于统计每个字符出现的次数
  • 循环一遍str将字符映射到count索引中
  • 再循环一遍str查找第一次出现的字符,找到后输出并break结束循环,其中定义found用于标记是否找到
代码实现
#include<stdio.h>
#include<string.h>
int main(){
	char str[1100]; 
	scanf("%s", &str); 
	int len = strlen(str); 
	int count[26] = {0}; 
	for (int i = 0; i < len; i++) {
		count[str[i] - 'a']++; 
	}
	int found = 0; 
	for (int i = 0; i < len; i++) {
		if (count[str[i] - 'a'] == 1) {
			printf("%c", str[i]); 
			found = 1; 
			break; 
	    }
	}
	if (found == 0) {
		printf("no"); 	
	}
	return 0; 
}

素数回文数的个数

[B2136 素数回文数的个数 - 洛谷]

题目描述

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

输入格式

一个大于 11 小于 10000 的整数 n。

输出格式

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

输入输出样例 #1
输入 #1
23
输出 #1
1
说明/提示

回文数指左右对称的数,如:11,12121。

考查知识点

素数,回文数的判断

解题思路
  • 定义两个函数isPrimeisPalindrome分别判断是否符合素数和回文数
  • isPrime:一个数小于等于 1 直接返回 0 ,一定不为素数。若大于等于 2 ,检查是否存在有除了自己和 1 以外的余数,有则返回 0 ,说明不是素数。其中因数只用检查到其平方根
  • isPalindrome:定义反转后的数 reversed 并初始化为 0 ,定义num替换原数x,通过while循环计算反转后的数,即反转后的数每次循环乘以 10 加上原数取余(最低位)的数,相当于原数的最低位作为反转后的数的最高位。最后检查反转后的数是否等于原数来判断是否为回文数
代码实现
#include<stdio.h>
#include<math.h>
int isPrime(int x) {
	if (x <= 1) {
		return 0; 
	}
	for (int i = 2; i <= sqrt(x); i++) {
		if (x % i == 0) {
			return 0; 
		}
	}
	return 1; 
}
int isPalindrome(int x) {
	int reversed = 0; 
	int num = x; 
	while (x != 0) {
		reversed = reversed * 10 + x % 10; 
		x /= 10; 
	}
	return num == reversed; 
}
int main() {
	int n;
	scanf("%d", &n); 
	int count = 0; 
	for (int i = 11; i <= n; i++) {
		if (isPrime(i) && isPalindrome(i)) {
			count++; 
		}
	}
	printf("%d", count); 
	return 0; 
}

基因相关性

[B2111 基因相关性 - 洛谷]

题目描述

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

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

输入格式

有三行,第一行是用来判定出两条 DNA 序列是否相关的阈值,随后 2行是两条 DNA 序列(长度不大于 500)。

输出格式

若两条 DNA 序列相关,则输出 yes,否则输出no

输入输出样例 #1
输入 #1
0.85
ATCGCCGTAAGTAACGGTTTTAAATAGGCC
ATCGCCGGAAGTAACGGTCTTAAATAGGCC
输出 #1
yes
考查知识点

数组存储字符串

解题思路
  • 将两个DNA序列存入两个数组DNA1,DNA2
  • 遍历一个数组逐个比对每个字符是否相同
  • 计算相同字符数个数same和所占比例rate,对比阈值threshold和相同字符所占比例rate。若大于阈值,则输出yes,否则输出no
代码实现
#include<stdio.h>
#include<string.h>
int main() {
	double threshold; 
	scanf("%lf", &threshold); 
	char DNA1[501], DNA2[501]; 
	scanf("%s", &DNA1); 
	scanf("%s", &DNA2); 
	int len = strlen(DNA1); 
	int same = 0; 
	for (int i = 0; i < len; i++) {
		if (DNA1[i] == DNA2[i]) {
			same++; 
		}
	}
	double rate = (double)same / len; 
	if (rate >= threshold) {
		printf("yes");  
	} else {
		printf("no"); 
	}
	return 0; 
}

欢乐的跳

[P1152 欢乐的跳 - 洛谷]

题目描述

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

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

输入格式

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

输出格式

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

输入输出样例 #1
输入 #1
4 1 4 2 3
输出 #1
Jolly
输入输出样例 #2
输入 #2
5 1 4 2 -1 6
输出 #2
Not jolly
说明/提示

1 <= n <= 1000

考查知识点

数组

解题思路
  • 读取数组number,初始化差的绝对值数组diffs,定义found并初始化为 1 标记差值是否出现
  • 遍历数组,计算两个连续元素之间差的绝对值diff
  • 检查差的绝对值是否在要求范围内且出现一次
  • 根据found标记输出。若为 1 ,则输出Jolly,否则输出Not jolly
代码实现
#include<stdio.h>
#include<stdlib.h>
int main() {
	int n; 
	scanf("%d", &n); 
	int number[n]; 
	for (int i = 0; i < n; i++) {
		scanf("%d", &number[i]);
	}
	int diffs[n]; 
	for (int i = 0; i < n; i++) {
		diffs[i] = 0; 
	}
	int found = 1; 
	for (int i = 1; i < n; i++) {
		int diff = abs(number[i] - number[i - 1]); 
		if (diff >= 1 && diff <= n - 1) {
			if (diffs[diff - 1] == 0) {
				diffs[diff - 1] = 1; 
			} else {
				found = 0; 
				break; 
			}
		} else {
			found = 0; 
			break; 
		}
	}
	if (found == 1) {
		printf("Jolly"); 
	} else {
		printf("Not jolly"); 
	}
	return 0; 
}

开关灯

[B2092 开关灯 - 洛谷]

题目描述

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

输入格式

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

输出格式

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

输入输出样例 #1
输入 #1
10
输出 #1
1 4 9
输入输出样例 #2
输入 #2
5
输出 #2
1 4
考查知识点

寻找因数

解题思路
  • 初始化count来存储因数个数
  • 因为偶数个人操作后,灯的状态不变(开),奇数个人操作后,状态相反。又因为只有完全平方数的因数为奇数,因此最终关闭的灯为完全平方数的灯
代码实现
#include<stdio.h>
#include<math.h>
int main() {
	int n; 
	scanf ("%d", &n); 
	for (int i = 1; i <= sqrt(n); i++) {
		printf ("%d ", i * i);
	}
	return 0; 
}

二进制分类

[B2140 二进制分类 - 洛谷]

题目描述

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

例如:

(13)_{10}=(1101)_2,其中 1 的个数为 3,0 的个数为 1,则称此数为 A 类数;

(10)_{10}=(1010)_2,其中 1 的个数为 2,0 的个数也为 2,称此数为 B 类数;

(24)_{10}=(11000)_2,其中 1 的个数为 2,0 的个数为 3,则称此数为 B 类数;

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

输入格式

输入 n。

输出格式

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

输入输出样例 #1
输入 #1
7
输出 #1
5 2
考查知识点

十进制转二进制

解题思路
  • ten_two函数:初始化转化为二进制后的数result为 0 ,使用while循环,通过 t 每次乘 10 将原十进制数除以二后的余数从个位起存入,最终得到转化后的二进制数
  • AB:初始化二进制数中 0 和 1 的个数为 0 ,使用while 循环,将二进制数的最后一位读取,计算二进制数中 0 和 1 的个数,如果 1 的个数大于 0 的个数,返回 1 ,否则,返回 0
  • 计算A类数,B类数个数并输出
代码实现
#include<stdio.h>
int ten_two(int x) {
	int result = 0; 
	int t = 1; 
	while (x) {
		result += (t * (x % 2)); 
		x /= 2; 
		t *= 10; 
	}
	return result; 
}
int AB(int result) {
	int countone = 0;
	int countzero = 0;
	while (result) {
		if (result % 10 == 0) {
			countzero++;
		} else {
			countone++;
		}
		result /= 10;
	}
	if (countone > countzero) {
		return 1;
	} else {
		return 0;
	}
}
int main() {
	int n; 
	scanf("%d", &n); 
	int A = 0; 
	int B = 0; 
	for (int i = 1; i <= n; i++) {
		int num = ten_two(i); 
		if (AB(num) == 1) {
			A++;
		} else {
			B++;
		}
	}
	printf("%d %d", A, B);
	return 0; 
}

点亮灯笼

[B3639 T2 点亮灯笼 - 洛谷]

题目描述

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

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

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

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

输入格式

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

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

输出格式

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

输入输出样例 #1
输入 #1
5 4
1
3
1
2
输出 #1
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。

考查知识点

数组

解题思路
  • 定义数组lantern存储灯笼开闭状态并初始化所有灯笼为关闭状态,即数组为0。则 1 为开,0 为闭
  • 定义button为按钮编号作为索引。数组从 0 开始,所以button作为索引时需先减 1
  • 反转指定灯笼及相邻两个灯笼状态。反转前一个时,需button - 1 + n取余n以确保前一个仍为所有灯笼之一。反转后一个时,需button + 1取余n。因为该灯笼放置为环形
  • 输出最终状态
代码实现
#include<stdio.h>
int main() {
	int n, m; 
	scanf("%d %d", &n, &m); 
	int lantern[n]; 
	for (int i = 0; i < n; i++) {
		lantern[i] = 0; 
	} 
	for (int i = 0; i < m; i++) {
		int button; 
		scanf("%d", &button); 
		button--; 
		lantern[button] = 1 - lantern[button]; 
		lantern[(button + 1) % n] = 1 - lantern[(button + 1) % n]; 
		lantern[(button - 1 + n) % n] = 1 - lantern[(button - 1 + n) % n];  
	}
	for (int i = 0; i < n; i++) {
		printf("%d ", lantern[i]); 
	}
	return 0; 
} 

查找

[P2249 【深基13.例1】查找 - 洛谷]

题目描述

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

输入格式

第一行 2 个整数 n 和 m,表示数字个数和询问次数。

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

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

输出格式

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

输入输出样例 #1
输入 #1
11 3
1 3 3 3 5 7 9 11 13 15 15
1 3 6
输出 #1
1 2 -1
说明/提示

数据保证,1 <= n <= 10^6=,0 <= a_i,q <= 10^9,1 <= m <= 10^5

本题输入输出量较大,请使用较快的 IO 方式。

考查知识点

二分查找

解题思路
  • 定义数组arr为待查找的数组,num为需要查找的数的数组
  • 二分查找:对于一个有序数列,先定义左边界为 0 ,右边界为n-1,然后使用while循环来确保不越界,定义mid为中间数下标。用if语句判断,若所找数小于等于中间值,说明所找值在中间值左侧,因此更新r值为mid,相反同理更新l值为mid + 1。循环直至找到待查询的数字,输出下标为l + 1,若未找到,则输出-1
代码实现
#include<stdio.h>
int main() {
	int n, m; 
	scanf("%d%d", &n, &m); 
	int arr[n], num[m]; 
	for (int i = 0; i < n; i++) {
		scanf("%d", &arr[i]); 
	}
	for (int i = 0; i < m; i++) {
		scanf("%d", &num[i]); 
	} 
	for (int i = 0; i < m; i++) {
		int l = 0, r = n - 1; 
		while (l < r) {
		    int mid = (l + r) / 2; 
			if (num[i] <= arr[mid]) {
				r = mid; 
			} else {
				l = mid + 1; 
			}
		}
		if (arr[l] == num[i]) {
			printf("%d ", l + 1); 
		} else {
			printf("-1 "); 
		}
	}
	return 0; 
} 

排队接水

[P1223 排队接水 - 洛谷]

题目描述

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

输入格式

第一行为一个整数 n。

第二行 n 个整数,第 i 个整数 T_i 表示第 i 个人的接水时间 T_i。

输出格式

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

输入输出样例 #1
输入 #1
10 
56 12 1 99 1000 234 33 55 99 812
输出 #1
3 2 7 8 1 4 9 6 10 5
291.90
说明/提示

1<= n <= 1000,1<= t_i <= 10^6,不保证 t_i 不重复。

考查知识点

排序

解题思路
  • 定义数组watert,wait,index分别为每个人的接水时间,每个人的等待时间,重新排序后的下标
  • 冒泡排序使新序列为等待时间最短的序列并调换下标
  • 冒泡排序:遍历数组,从数组第一个元素开始,依次比较每对相邻的元素。若前一个元素大于后一个元素,则交换他们的位置和下标,重复以上直到排序完成
  • 计算每个人的等待时间,即前一个人的等待时间和前一个人的接水时间的总和
  • 计算总等待时间及其平均值,输出新序列下标
代码实现
#include<stdio.h>
int main() {
    int n;
    int watert[1001], wait[1001], index[1001]; 
    long long watersum = 0, waitsum = 0; 
    scanf("%d", &n); 
    for (int i = 0; i < n; i++) {
        scanf("%d", &watert[i]); 
        index[i] = i; 
    }
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - 1 - i; j++) {
            if (watert[j] > watert[j + 1]) {
                int temp = watert[j]; 
                watert[j] = watert[j + 1]; 
                watert[j + 1] = temp; 
                temp = index[j]; 
                index[j] = index[j + 1]; 
                index[j + 1] = temp; 
            }
        }
    }
    wait[0] = 0; 
    for (int i = 1; i < n; i++) {
    	wait[i] = wait[i - 1] + watert[i - 1]; 
        waitsum += wait[i]; 
    }
    double average = (double) waitsum / n; 
    for (int i = 0; i < n; i++) {
        printf("%d ", index[i] + 1); 
    } 
    printf("\n%.2lf", average); 
    return 0; 
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值