目录
一.选择题
1.[单选题] 以下for循环的执行次数是()
for(int x = 0,y = 0;(y = 123) && (x < 4);x++);
A 无限循环 B 循环次数不定 C 4次 D 3次
解析:
先来回顾以下for循环的构成:
for(初始化部分;条件判断部分;调整部分)
{
循环内容
}
所以我们知道,x和y被初始化为0。循环条件是(y = 123) && (x < 4),这部分呢是这样的,当&&两边的条件都成立,条件部分才成立。而这里的y = 123,是赋值,不是等于,所以y是恒成立,所以这里就只需看 x < 4。所以,x从0到3,for循环4次。所以选C。
2.[单选题]以下程序的运行结果是()
#include<stdio.h>
int main()
{
printf("%s, %5.3s\n","computer","computer");
return 0;
}
A computer , puter B computer , com C computer , computer D computer , compu.ter
解析:
这道题主要考的是对%5.3s的理解,也就是%m.ns。
先来说说%s,%s代表着打印字符串,然后遇到\n的时候就会停止,每个字符串的最后都会有\n隐藏起来。
然后来着重讲解%m.ns:↓
m:输出字符串的宽度
n:从左边截取字符串n个字符,然后右对齐,不过不够则补空格。
当字符串的长度 > n >m的时候,m的功能失效
当n > 字符串的时候,所有功能正常
所以对于这道题的%5.3s,就是对"computer"截取"com",并且向右对齐5个字符宽带,也就是在c前面添加两个空格。所以这道题选B。
3.[单选题]下列main()函数执行后的结果为()
int func()
{
int i, j, k = 0;
for(i = 0, j = -1;j = 0;i++, j++)
{
k++;
}
return k;
}
int main()
{
cout << (func());
return 0;
}
A -1 B 0 C 1 D 2
解析:
这里也是考察了for循环,有了第一题的经验,我们可以判断出,在条件判断部分,j = 0是赋值语句,而且赋值的是0,所以条件为假,for循环一次也不执行,所以答案是B,k==0.
4.[单选题]下面的程序输出是什么?
#include<stdio.h>
int main()
{
int a = 1,b = 2,c = 3,d = 0;
if(a == 1 && b++ ==2)
if(b!=2 || c--!=3)
printf("%d,%d,%d\n",a,b,c);
else
printf("%d,%d,%d\n",a,b,c);
else
printf("%d,%d,%d\n",a,b,c);
return 0;
}
A 1,2,3 B 1,3,2 C 3, 2 ,1 D 1,3,3
解析:
这里考察的是前后置++,逻辑或和逻辑与,和if else配套的理解。因为 else是与最近的if配套的,而且每个if或else都没有{},所以,第一个if是与最后一个else配套,第二个if是与第二个else配套。
接着判断++ &&等等,第一个if语句中,a==1与b==2,条件为真,判断完后,b是后置++,所以此时才是b==3.所以,最后是输出:a ==1,b==3,c==3.答案是D
5.[单选题]若有定义语句: int a=10 ; double b=3.14 ; 则表达式 'A'+a+b 值的类型是()
A char B int C double D float
解析:这里考察的是数据类型自动提升的知识点。字节小的类型在与字节大的类型运算的时候,小的会向大的提升。在这道题中,A是字符,char,a是int,b的double,所以最大的是b,也就是double,所以A和a都向double提升,最终运算出来的值是double类型的。
6.[单选题]在int p[][4] = {{1},{3,2},{4,5,6},{0}};中,p[1][2]的值是()
A 1 B 0 C 6 D 2
解析:这里考察的是二维数组的基本知识。从题目中我们可以看出p是p[4][4]的二维数组,然后展开来看,就是{{1,0,0,0},{3,2,0,0},{4,5,6,0},{0,0,0,0}}。所以,由下标的看,p[1][2]就是第二行第三列的值,也就是{{1,0,0,0},{3,2,0,0},{4,5,6,0},{0,0,0,0}}红色那个0.所以答案是B
7.[单选题]选择表达式 11|10 的结果(本题数值均为十进制)()
A 11 B 10 C 8 D 2
解析:
这道题就是考察逻辑或的运算。
将11和10用二进制数来表示,然后逻辑或就是有1为1,全0是0.
11:0000 1011
10:0000 1010
————————
| :0000 1011----11
所以答案是A
8.[单选题]fun(21)运行结果()
int fun(int a)
{
a^=(1<<5)-1;
return a;
}
A 10 B 5 C 3 D 8
解析:
这道题考察的是左移和异或的运算。
先执行=右边的,因为原式等于a = a^((1<<5)-1);
1<<5:就是将1向左移5位:
1的二进制位:0000 0001——>左移后:0010 0000——>减1:0001 1111
a^(0001 1111):21——>0001 0101^0001 1111——>0000 1010——>10
所以答案是A。
9.[单选题]若有定义语句:int year=1009,*p=&year;以下不能使变量 year 中的值增至 1010 的语句是()
A *p+=1; B (*p)++; C ++(*p) D *p++
解析:
这里考察的是指针的基本知识,对指针的创建和解引用。
*p=&year,就是说p指向了year的地址。
对于A:因为*的优先级高于+=,所以是先对p进行解引用然后加1,可以year的值加1,增值1010.
对于B和C:(*p)是对p解引用,此时指向的是year的值,然后++,前置后置都能++,所以也行
对于D:因为后置++的优先级高于*号,所以是先对p这个指针指向的地址加加,再进行解引用
10.[单选题]下面关于"指针"的描述不正确的是()
A 当使用free释放掉一个指针内容后,指针变量的值被置为NULL
B 32位系统下任何类型指针的长度都是4个字节
C 指针的数据类型声明的是指针实际指向内容的数据类型
D 野指针是指向未分配或者已经释放的内存地址
解析:
这里考察的是对指针的理解。
A:当free掉一个指针内容后,是这个指针找不到曾经指向的内容了,不是说内容被置为NULL,如果不及时主动置空,就会变成野指针。
BCD很明显是对的。
对于野指针的避免:①在创建指针的时候初始化 ②在free后置空 ③不要越界访问
二.编程题
1.组队竞赛
题目描述:牛牛举办了一次编程比赛,参加比赛的有3*n个选手,每个选手都有一个水平值a_i.现在要将这些选手进行组队,一共组成n个队伍,即每个队伍3人.牛牛发现 队伍的水平值等于该队伍队员中第二高水平值。 例如: 一个队伍三个队员的水平值分别是3,3,3.那么队伍的水平值是3 一个队伍三个队员的水平值分别是3,2,3.那么队伍的水平值是3 一个队伍三个队员的水平值分别是1,5,2.那么队伍的水平值是2 为了让比赛更有看点,牛牛想安排队伍使所有队伍的水平值总和最大。 如样例所示: 如果牛牛把6个队员划分到两个队伍 如果方案为: team1:{1,2,5}, team2:{5,5,8}, 这时候水平值总和为7. 而如果方案为: team1:{2,5,8}, team2:{1,5,5}, 这时候水平值总和为10. 没有比总和为10更大的方案,所以输出10.
输入描述:
输入的第一行为一个正整数n(1 ≤ n ≤ 10^5) 第二行包括3*n个整数a_i(1 ≤ a_i ≤ 10^9),表示每个参赛选手的水平值.
输出描述:
输出一个整数表示所有队伍的水平值总和最大值.
示例一:
输入:
2
5 2 8 5 1 5
输出:10
解析:这道题,我们第一个想到的是将数据进行排序,然后找到我们需要的那个数,并且加起来,
通过例子我们知道,需要找的数就是5和5,但我们如何去保证我们找到的数是所需的数呢?每次选n个数进行分组,怎么选是个问题!我们需要保证,分出来的组,一定有最大值和次大值,根据这个思路,我们就有想法了!比如这道题,就是在左边取1个,在右边取两个,这样的话,就能够保证我们分出来的组别是对的。有人会想问:那为什么不在左边取两个,右边取一个呢?如果我们这样取,就会分为:1 2 8 为一组,5 5 5为一组,这样不能保证每一组中有最小,最大,次大的值!
分好组后,我们该怎么取这个数呢?这里有个公式,那就是arr.size()-2*(i+1);通过这个公式便能找出分组后的每一组的次大值!
最后加起来,就可以了。
总结:分两步:①理解如何取分组,即需要保证有最大值,最小值,次大值。
②理解如何去找每一组的次大值,使用公式arr.size()-2*(i+1)
代码如下:
#include<iostream> #include<algorithm> #include<vector> using namespace std; int main() { int n = 0; while (cin >> n) { long long sum = 0; vector<int> arr; arr.resize(3 * n); for (int i = 0; i < (3 * n); i++) { cin >> arr[i]; } sort(arr.begin(), arr.end()); for (int i = 0; i < n; i++) { sum += arr[arr.size() - (2 * (i + 1))]; } cout << sum << endl; } return 0; }
2.删除公共字符
题目描述:输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。例如,输入”They are students.”和”aeiou”,则删除之后的第一个字符 串变成”Thy r stdnts.”
输入描述:每个测试输入包含2个字符串
输出描述:输出删除后的字符串
示例一:
输入:
They are students.
aeiou
输出:Thy r stdnts.
解析:
如果使用暴力解法,将第二个字符串弄到第一个字符串中,那样的话,时间复杂度为O(N^2).这样是不行的。
我们通过哈希映射思想来解题。使用一个数组来记录第二个字符串,比如,字符串aeiou,那么,数组就能将aeiou分别对应的ASCII码值对应的位置赋值为1。接着再通过遍历第一个字符串,判断在数组中将每个字符对应的位置的值是否为0,如果是,则将其追加到新的字符串ret中,最后打印ret。
代码如下:
#include<iostream> #include<string> int main() { string str1, str2; getline(cin, str1); getline(cin, str2); int hashtable[256] = { 0 }; for (int i = 0; i < str2.size(); i++) { hashtable[str2[i]]++; } string ret; for (int i = 0; i < str1.size(); i++) { if (hashtable[str1[i]] == 0) { ret += str1[i]; } } cout << ret << endl; return 0; }