移动应用开发实验室二面面试题
第一题:小车问题
题目描述
甲、乙两人同时从 A 地出发要尽快同时赶到 B 地。出发时 A 地有一辆小车,可是这辆小车除了驾驶员外只能带一人。已知甲、乙两人的步行速度一样,且小于车的速度。问:怎样利用小车才能使两人尽快同时到达。
输入格式:
仅一行,三个实数,分别表示 AB 两地的距离 s,人的步行速度 a,车的速度 b。
输出格式:
两人同时到达 B 地需要的最短时间,保留 66 位小数。
sample 1
Input | output |
120 5 25 | 9.600000 |
题解:
这道题可以根据甲乙两人同时到达终点列方程,驾驶员带一个行驶一段距离x之后返回去接正在行走的另一个人,碰到之后前往终点,甲乙两人同时到达。即t=x/b+(s-x)/a,(s-x)/a=2*(2*x/(a+b)-x/b)+(s-x)/b,化简得x=(b+a)*s/(b+3*a)。
#include<stdio.h>
int main()
{
float a, b, t, s;
scanf("%f %f %f", &s, &a, &b);
int x = 0;
x = (b + a) * s / (b + 3 * a);
t = x / b + (s - x) / a;
printf("%.6f", t);
}
第二题: 笨小猴
题目描述:
笨小猴的词汇量很小,所以每次做英语选择题的时候都很头疼。但是他找到了一种方法,经试验证明,用这种方法去选择选项的时候选对的几率非常大!
这种方法的具体描述如下:假设 maxn是单词中出现次数最多的字母的出现次数,minn 是单词中出现次数最少的字母的出现次数,如果 maxn−minn 是一个质数,那么笨小猴就认为这是个 Lucky Word,这样的单词很可能就是正确的答案。
输入格式:
一个单词,其中只可能出现小写字母,并且长度小于 100。
输出格式:
共两行,第一行是一个字符串,假设输入的的单词是 Lucky Word,那么输出 Lucky Word
,否则输
出 No Answer
;
第二行是一个整数,如果输入单词是 Lucky Word
,输出 maxn−minn的值,否则输出 0。
sample1
Input | Output |
error | Lucky Word 2 |
sample 2
Input | Output |
olympic | No Answer 0 |
题解:
打印出100以内的所有质数用遍历字符串数组,用新的数组记录字母出现的次数,遍历字母,比较并找出新的数组的最大最小值,相减,再遍历打印出来的质数,若是质数,则输出Lucky Word及质数,否则输出No Answer和0。
#include<stdio.h>
#include<string.h>
int main() {
char s[100] = { 0 };
int sum[100] = { 0 };
int max = 0, min = 100;
int prime[25] = { 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97 };
scanf("%s", s);
int n = strlen(s);
for (int i = 0; i < n; i++) {
sum[s[i] - 'a']++;
}
for (int i = 0; i < 100; i++) {
if (sum[i] > max) {
max = sum[i];
} else if (sum[i] > 0 && sum[i] < min) {
min = sum[i];
}
}
for (int i = 0; i < 25; i++) {
if (max - min == prime[i]) {
printf("Lucky Word\n%d", max - min);
return 0;
}
}
printf("No Answer\n0");
return 0;
}
第三题:拯救oibh总部
题目背景:
oibh 总部突然被水淹没了!现在需要你的救援……
题目描述:
oibh 被突来的洪水淹没了,还好 oibh 总部有在某些重要的地方起一些围墙。用 *
号表示,而一个四面被围墙围住的区域洪水是进不去的。
oibh 总部内部也有许多重要区域,每个重要区域在图中用一个 0
表示。
现在给出 oibh 的围墙建设图,问有多少个没被洪水淹到的重要区域。
输入格式:
第一行为两个正整数 x,y。
接下来 x 行,每行 y 个整数,由 *
和 0
组成,表示 oibh 总部的建设图。
输出格式:
输出没被水淹没的 oibh 总部的 0
的数量。
sample 1
Input | Output |
4 5 00000 00*00 0*0*0 00*00 | 1 |
sample 2
Input | Output |
5 5 ***** *0*0* **0** *0*0* ***** | 5 |
题解:
这道题是深度优先搜索,DFS被用来标记所有被淹没的格子,用search函数,对当前格子的位置的相邻上下左右进行搜索遍历,如果相邻的格子未被洪水淹没,递归调用search函数进行处理。最外层如果是空,则洪水一直向里走,从最外层开始,搜第一列和最后一列格子,在搜索第一行和最后一行格子,最后再搜空的格子,输出空格子数。
#include<stdio.h>
int n, m, s = 0;
int kx[5] = { 0,1,-1,0,0 };
int ky[5] = { 0,0,0,1,-1 };
int a[501][501];
void search(int x, int y) {
a[x][y] = 1;//先标记被淹没了
for (int i = 1; i <= 4; i++) {//搜索
int x0 = x + kx[i];
int y0 = y + ky[i];
if (x0 > 0 && x0 <= n && y0 > 0 && y0 <= m && a[x0][y0] == 0)search(x0, y0);
}
}
int main() {
scanf("%d%d", &n, &m);
char e;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
scanf(" %c", &e);
if (e == '*') {
a[i][j] = 1;//如果是障碍就输入1
} else {
a[i][j] = 0;//可以过就是0
}
}
}
for (int i = 1; i <= n; i++) {//搜索第一列和最后一列
if (a[i][1] == 0) search(i, 1);//如果有能过的就搜索
if (a[i][m] == 0) search(i, m);
}
for (int i = 1; i <= m; i++) {//搜索第一行和最后一行的格子
if (a[1][i] == 0) search(1, i);
if (a[n][i] == 0) search(n, i);
}
for (int i = 1; i <= n; i++) {//最后搜索没有被淹的格子
for (int j = 1; j <= m; j++) {
if (a[i][j] == 0) {
s++;
}
}
}
printf("%d", s);
return 0;
}
第四题:对列安排
题目描述:
一个学校里老师要将班上 N 个同学排成一列,同学被编号为 1∼N,他采取如下的方法:
-
先将 1 号同学安排进队列,这时队列中只有他一个人;
-
2∼N 号同学依次入列,编号为 i 的同学入列方式为:老师指定编号为 i 的同学站在编号为 1∼(i−1) 中某位同学(即之前已经入列的同学)的左边或右边;
-
从队列中去掉 M 个同学,其他同学位置顺序不变。
在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。
输入格式:
第一行一个整数 N,表示了有 N 个同学。
第 2∼N 行,第 i 行包含两个整数 k,p,其中 k为小于 i 的正整数,p 为 0或者 1。若 p 为 0,则表示将 i 号同学插入到 k 号同学的左边,p 为 1 则表示插入到右边。
第N+1 行为一个整数 M,表示去掉的同学数目。
接下来 M 行,每行一个正整数 x,表示将 x 号同学从队列中移去,如果 x 号同学已经不在队列中则忽略这一条指令。
输出格式:
一行,包含最多N 个空格隔开的整数,表示了队列从左到右所有同学的编号。
sample 1
Input | Output |
4 1 0 2 1 1 0 2 3 3 | 2 4 1 |
题解:
这道题我的思路是用数组模拟双向链表,定义一个学生结构体,如果输入的p的值是1则将当前节点插入节点k右边,否则插入左边。通过m的值表示要删除的节点数量,用循环读取要删除节点的编号,并将对应节点的id置1,表示需要被删除。注意初始化,我们可以定义第0个学生,从第0个学生的右手牵起,再到0结束。最后,用循环遍历链表,输出未被删除的节点编号。
#include<stdio.h>
int n, m;
struct Stdent {
int l, r;
int id;
}s[1000005];
int main() {
scanf("%d", &n);
for (int i = 2; i <= n; i++) {
int k, p;
scanf("%d%d ", &k, &p);
if (p == 1) {
s[i].r = s[k].r;
s[i].l = k;
s[s[k].r].l = i;
s[k].r = i;
} else {
s[i].l = s[k].l;
s[i].r = k;
s[s[k].l].r = i;
s[k].l = i;
}
}
scanf("%d", &m);
for (int i = 1; i <= m; i++) {
int x;
scanf("%d", &x);
s[x].id = 1;//标记要删除的人
}
int now;
for (int i = 1; i <= n; i++) {
if (s[i].l == 0 && s[i].id != 1) {
now = i;
}
}
while (now) {
if (s[now].id == 0) {
printf("%d ", now);
}
now = s[now].r;
}
return 0;
}
第五题:句子反转
题目描述:
给定一行句子,每个词之间用空格隔开,要么是全小写英文单词,要么是全大写英文单词,要么是自然数。
要求将这些单词倒序输出。而且对于每个单词,如果是小写词,应当转为大写;如果是大写词,应当转为小写;如果是自然数,应该倒转输出。
举一个例子:
we choose TO go 2 the 123 moon
程序应当输出:
MOON 321 THE 2 GO to CHOOSE WE
输入格式:
仅一行,即需要反转的句子。
输出格式:
仅一行,表示程序对句子的处理结果。
Input | Output |
we choose TO go 2 the 123 moon | MOON 321 THE 2 GO to CHOOSE WE |
题解:
这道题主要考察字符串的大小写转化,字符串整体上逆置,先判断是否是字母,是就大小写转换,并逐个输出,若第一个字符是数字,则逆序输出,若不是数字,直接输出该单词,当不是最后一个单词时,在后面添加空格。
#include<stdio.h>
#include<string.h>
int main() {
char ch[6010];
int m, n, i;
gets(ch);
m = strlen(ch) - 1;
n = strlen(ch) - 1; //使m,n指向最后一个字符
while (m > 0) {
while (m > 0 && ch[m] != ' ') {
m--; //此时m指向空格
}
if (ch[m + 1] <= 'Z' && ch[m + 1] >= 'A' || ch[m + 1] <= 'z' && ch[m + 1] >= 'a') {
if (m > 0) {
if (ch[m + 1] <= 'Z' && ch[m + 1] >= 'A') {
for (i = m + 1; i <= n; i++) {
ch[i] = ch[i] - 'A' + 'a';
printf("%c", ch[i]);
}
} else {
for (i = m + 1; i <= n; i++) {
ch[i] = ch[i] - 'a' + 'A';
printf("%c", ch[i]);
}
}
}
if (m == 0) {
if (ch[m] <= 'Z' && ch[m] >= 'A') {
for (i = 0; i <= n; i++) {
ch[i] = ch[i] - 'A' + 'a';
printf("%c", ch[i]);
}
} else {
for (i = 0; i <= n; i++) {
ch[i] = ch[i] - 'a' + 'A';
printf("%c", ch[i]);
}
}
}
} else {
if (m > 0) {
for (i = n; i > m; i--) {
printf("%c", ch[i]);
}
} else {
for (i = n; i >= m; i--) {
printf("%c", ch[i]);
}
}
}
if (m > 0)
printf(" ");
m--;
n = m;
}
}
第六题:明明的随机数
题目描述:
明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了 N 个 1 到 1000 之间的随机整数 (N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。
输入格式:
输入有两行,第1行为1正整数,表示所生成的随机数的个数N。
第2行有N个用空格隔开的正整数,为所产生的随机数。
输出格式:
输出也是两行,第1行为1个正整数 M,表示不相同的随机数的个数。
第2行为M个用空格隔开的正整数,为从小到大排好序的不相同的随机数。
sample 1
Input | Output |
10 20 40 32 67 40 20 89 300 400 15 | 8 15 20 32 40 67 89 300 400 |
题解:
这道题的整体思路是先进行排序,再去充,采用冒泡排序按照从小到大排序,之后开辟一个新的数组用来存储不相同的元素再输出,用count来记录不相同元素的个数再输出。
#include<stdio.h>
void sort(int* arr, int n) {
int i = 0;
for (i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int p = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = p;
}
}
}
}
int main() {
int n, arr[100] = { 0 };
int i = 0, j = 0;
int count = 1;
scanf("%d", &n);
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
sort(arr, n);
int s[100];
s[0] = arr[0];
for (j = 1; j < n; j++) {
if (arr[j] == arr[j - 1])
continue;
else
s[count++] = arr[j];
}
printf("%d\n", count);
for (int i = 0; i < count; i++) {
printf("%d ", s[i]);
}
return 0;
}
第七题:小A的糖果
题目描述:
小 A 有 n 个糖果盒,第 i 个盒中有 ai 颗糖果。
小 A 每次可以从其中一盒糖果中吃掉一颗,他想知道,要让任意两个相邻的盒子中糖的个数之和都不大于 x,至少得吃掉几颗糖。
输入格式:
输入的第一行是两个用空格隔开的整数,代表糖果盒的个数 n 和给定的参数 x。
第二行有 n 个用空格隔开的整数,第 i 个整数代表第 i 盒糖的糖果个数 ai。
输出格式:
输出一行一个整数,代表最少要吃掉的糖果的数量。
sample
Input | Output |
3 3 2 2 2 | 1 |
6 1 1 6 1 2 0 4 | 11 |
5 9 3 1 4 1 5 | 0 |
题解:
这道题考察贪心算法,局部最优达到整体最优解,遍历数组,如果相邻元素之和大于x,一次要吃掉最少的糖果,即元素之和减去x之后,后一个糖果数为x减去前一个盒子的糖果数。
#include<stdio.h>
int main() {
long long sum = 0;
int arr[100005];
int n, x;
scanf("%d%d ", &n, &x);
for (int i = 1; i <= n; i++) {
scanf("%d ", &arr[i]);
}
for (int i = 0; i < n; i++) {
if (arr[i] + arr[i + 1] > x) {
sum = sum + arr[i] + arr[i + 1] - x;
arr[i + 1] = x - arr[i];
}
}
printf("%lld", sum);
return 0;
}