笔试强训01|组队竞赛|删除公共字符(C++)

单选
1. 单选

以下for循环的执行次数是()

for(int x = 0, y = 0; (y = 123) && (x < 4); x++);

A. 是无限循环
B. 循环次数不定
C. 4次
D. 3次

解析
for(初始化部分;条件判断部分:调整部分)
{
	循环语句部分;
}
初始化部分:用于循环变量的初始化
条件判断部分:用于判断循环什么时候结束
调整部分:用于循环变量的调整
循环语句部分
  • 初始化部分,将x初始化为0,y初始化为0,并且初始化部分只会进行一次
  • 条件判断部分,用逻辑与连接起来的表达式,左右都为真,整体才为真,其他情况都为假。
    • 左边为赋值语句,给变量y赋值为123,结果为123,非0,为真
    • 整个表达式的结果与右边有关,x<4时整个表达式的结果为真
  • 调整部分:x++,每次循环结束以后,x+1
  • x初始化为0,x<4时会进入循环,每次循环结束x+1
    • 所以当x=0,1,2,3时会进入循环,x=4时会结束循环
  • 所以for循环的执行次数是4次
  • 选C

2. 单选

以下程序的运行结果是()

#include <stdio.h>
int main(void) 
{ 
	printf("%s , %5.3s\n", "computer", "computer");
	return 0; 
}

A. computer , puter
B. computer , com
C. computer , computer
D. computer , compu.ter

解析
  • 不同的格式化去打印相同的字符串
    1. %s去打印字符串,遇到\0会停止打印
    2. 常量字符串在最后的位置会有一个\0
    • 所以第一个computer会完整的打印出来
  • %m.ns:m表示小数点前的数字,n表示小数点后的数字
    • m:表示输出字符串的宽度
    • n:表示左起截取目标字符串n个字符,并且是右对齐,补空格
    1. 当字符串长度>n>m时,m的作用就失效了,只受n控制,左起截取目标字符串n个字符进行输出即可
    2. 当n>字符串长度时,作用和%s是一样的,遇到字符串最后一个\0,就会停止打印
  • %5.3s:输出的字符串的宽度为5,然后左起截取目标字符串3个字符(com),左边差两个不够,补空格,( com)
  • 最后的结果:computer, com
  • 选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

解析
  • func函数定义了一个k变量初始化为0,最后将k的值返回出来,在main函数中输出出来
  • k变量每次在for循环中k++
  • 这个题的本质在问for循环能够执行多少次
    • 变量i初始化为0,j初始化为-1
    • 条件判断部分,是一个赋值语句,j赋值为零,这个条件的结果为0,是假的,所以不会进入for循环,k的变量的值是不会增加的,是将0这个值返回出去,进行输出
  • 所以正确结果就是0
  • 选B

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

解析
  • else语句:有就近匹配if语句原则
    • 所以第一个else和第二个if匹配,第一个if和最后一个else配套
  • 逻辑与表达式,两边的表达式都为真的时候,整个表达式才为真,否则都为假
    • 变量a等于1,和1比较,相等,表达式结果为真,
    • b++ == 2,因为是后置++,先拿b的值和2比较,也就是b等于2和2比较,相等,表达式结果为真,比较完以后,b++,b为3
    • 所以整体的表达式为真,进入第二个if语句
  • 逻辑或表达式,至少某一边的表达式为真的话,整个表达式为真
    • 左边b != 2,上一步b已经为3了,所以这里为真
  • 逻辑或有短路原则,左边的表达式为真的话,右边的表达式就不会执行
    • 所以直接进行printf语句,输出abc三个变量的值
  • a为1,b为3,c因为没有执行逻辑或右边的表达式,所以不会–,为3
  • 最后的结果是1,3,3
  • 选D

5.单选

若有定义语句:

int a=10 ; 
double b=3.14 ; 

则表达式'A'+a+b值的类型是()
A. char
B. int
C. double
D. float

解析
  • 定义了一个int类型的整型变量a,初始化为10,一个double类型的变量b,初始化为3.14
  • 问表达式字符A+变量a+变量b的类型是什么
  • 不同类型的表达式进行计算的时候,有自动提升的过程,表示范围小的数据类型会自动提升为表示范围大的数据类型
    • 字符A,char数据类型,占1个字节,范围-128~127
    • 变量a,int数据类型,占4个字节,范围-21亿~21亿
    • 变量b,double数据类型,占8个字节,范围2.3x10-308~1.7x10308
  • 所以计算的时候,char和int数据类型会自动提升为double数据类型,整个表达式的数据类型就是double数据类型
  • 选C

6.单选

int p[][4] = {{1}, {3, 2}, {4, 5, 6}, {0}};

中,p[1][2]的值是()
A. 1
B. 0
C. 6
D. 2

解析
  • 定义了一个二维数组,并且进行了初始化,在二维数组的声明中,可以看到,省略了行数,列是4列
  • 行可以通过初始化部分去获得,每个大括号表示一行,4个大括号表示4行,所以这个二维数组是4行4列的
  • 这里每一行都没有进行完全初始化,在没有初始化的部分会默认为0
  • 把二位数组整个写出来
    1000
    3200
    4560
    0000
  • 这里通过下标访问数组元素,二维数组中行和列都是从0开始,所以p[1][2]的值为0
  • 选B

7.单选

选择表达式 11|10 的结果(本题数值均为十进制)()
A. 11
B. 10
C. 8
D. 2

解析
  • 计算11按位或上10的结果
  • 先将十进制数字转为二进制数字
    • 11:0000 1011
    • 10:0000 1010
  • 按位或:对应的比特位至少有一个1,对应的结果就为1,
    • 11|10:0000 1011
    • 转换为十进制:11
  • 所以正确结果是11
  • 选A

8.单选
int fun (int a)
{ 
	a^=(1<<5)-1; 
	return a; 
}

fun(21)运行结果是()
A. 10
B. 5
C. 3
D. 8

解析
  • 先分析fun函数,根据int a传参,通过异或给参数赋值,再将结果返回出来
  • ^=:异或赋值,将a异或b的结果赋值给a
    • a^=b; -> a = a^b;
  • <<:左移运算符
    • 1<<5:0000 0001将它左移5位:0010 0000,转化为十进制:32
  • a^=(1<<5)-1 -> a = a^(1<<5)-1 -> a = a^31
    • a = 21^31
      • 21:0001 0101
      • 31:0001 1111
  • 按位异或:对应的比特位如果一个为0一个为1,则最后的结果为1,其他情况都为0
    • 21^31:000 1010
    • 转换为十进制:10
  • 选A

9.单选

若有定义语句:int year=1009,*p=&year;以下不能使变量 year 中的值增至 1010 的语句是()
A. *p+=1;
B. (*p)++;
C. ++(*p)
D. *p++

解析
  • 定义了year变量,赋初值1009
  • 将year变量的地址作为指针变量p的初始值
    • A:*运算符的优先级是要高于+=运算符的,所以先对指针变量p进行解引用,获取到指针所指向的地址的值,也就是year变量1009。再+=1,也就是将year1009+1赋给year变量,所以可以。
    • B、C:B选项和C选项的区别是前置和后置++,因为都带了括号,都是先对p变量进行解引用,获取到对应地址的值,也就是year1009,再进行++,所以可以满足条件
    • D:不可以。因为后置++的优先级高于*号,所以要先对p指针进行++,因为是后置++,所以在真正++之前先对p变量进行解引用,获取到year变量的值,再对指针p进行++,所以没有对year值进行++,所以不会
  • 选D

10.单选

下面关于"指针"的描述不正确的是()
A. 当使用free释放掉一个指针内容后,指针变量的值被置为NULL
B. 32位系统下任何类型指针的长度都是4个字节
C. 指针的数据类型声明的是指针实际指向内容的数据类型
D. 野指针是指向未分配或者已经释放的内存地址

解析

A:当用free释放掉一个指针以后,只是销毁了指针指向的空间,并没有将指针置空,此时指针指向一个已经被销毁的空间,这时就是野指针
造成野指针的原因
在定义指针的时候未进行初始化
在free掉指针后没有置空
越界访问,超越作用域去使用指针

  • 选A

编程题
1.编程题

组队竞赛__牛客网 (nowcoder.com)
知识点
排序 贪心

题目
  • 牛牛举办了一次编程比赛,参加比赛的有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.
解析

怎样分组使水平值总和更大

  • 思路
    • 首先对这一组数据进行排序:125558
    • 然后分别取第一个和后两个作为一组(1,5,8)(2,5,5,),这样水平值总和为10
    • 这样子取,第一组一定会拿到一个最高值和一个仅次于最高值的值,这样一定会包含一个比最大值更小的一个元素
  • 例251437698
    • 排序:123456789
    • 分组:(1,8,9)(2,6,7)(3,4,5)
    • 8+6+4=18,最优解
  • 那么,如何知道864在哪个地方
    • 推导公式:假设一个数组arr.len - 2*(i+1)
    • 对第一个例子来说,len = 6,当len = 6时,分为2组
      • 取一个for循环for(int i = 0; i < n;)
      • 当i=0时,6-2*1=4,正好是第五个数字的下标
      • 当i=1时,6-2*2=2,正好是第三个数字的下标
    • 对第二个例子来说,len = 9,当len = 9时,分为3组
      • 取一个for循环for(int i = 0; i < n;)
      • 当i=0时,9-2*1=7,正好是第八个数字的下标
      • 当i=1时,9-2*2=5,正好是第六个数字的下标
      • 当i=2时,9-2*3=3,正好是第四个数字的下标
        最后理一下顺序
  • 首先处理输入,把数据输入进来
  • 然后对数组排序
  • 最后根据公式取值
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main()
{
	//输入
	long long sum = 0;// 用于存储最终结果的变量 sum
	int n;
	cin >> n;// 输入一个整数 n,表示每组数据的大小
	vector<int> a;// 创建一个整型向量 a,用于存储输入的 3n 个数
	a.resize(3*n);// 调整向量 a 的大小为 3n,以存放输入的数据
	
	// 循环读取输入的 3n 个数
	for(int i = 0; i < 3*n; i++)
	{
		cin >> a[i];
	}
	
	// 将向量 a 中的元素从小到大排序
	std::sort(a.begin(),a.end());
	
	// 从排序后的向量 a 中选取每组中第二大的数,共选取 n 个数,并将它们累加到 sum 中
	for(int i = 0; i < n; i++)
	{
		sum = sum + a[a.size() - 2*(i+1)];
	}

	// 输出最终的累加结果 sum
	cout << sum << endl;
	return 0;
}

这段代码的功能是从输入中读取一个整数 n,表示每组数据的大小。然后,读取 3n 个整数,并存储到大小为 3n 的整数向量 a 中。接着,对向量 a 中的元素进行排序。最后,从排序后的向量 a 中选取每组中第二大的数,共选取 n 个数,并将它们累加到变量 sum 中,最终输出 sum 的值。

  • 由于牛客是循环输入,也可以用另一种
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main()
{
	int n;
	while(cin >> n)
	{
		long long sum = 0;
		vector<int> a;
		a.resize(3*n);
	
		for(int i = 0; i < 3*n; i++)
		{
			cin >> a[i];
		}
	
		std::sort(a.begin(),a.end());
	
		for(int i = 0; i < n; i++)
		{
			sum = sum + a[a.size() - 2*(i+1)];
		}
		cout << sum << endl;
	}
	return 0;
}

2.编程题

删除公共字符_牛客题霸_牛客网 (nowcoder.com)
知识点
字符串 模拟

题目
  • 输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。例如,输入”They are students.”和”aeiou”,则删除之后的第一个字符串变成”Thy r stdnts.”
  • 每个测试输入包含2个字符串
  • 输出删除后的字符串
    输入
    They are students.
    aeiou
    输出
    Thy r stdnts.
解析

输入的是字符,字符对ASCII表总共有256个
可以给一个数组,利用哈希的思想
第一个字符串abcdef
第二个字符串be
结果acdf

  1. 遍历第二个字符串str2上的每一个字符,把每一个对应的字符放到hash[]
    b的ASCII值是98,在数组98下标的位置上放b出现的次数,b第一次放进来,初始我为0,++显示1
    e放在相应的下标上,初始为0,++显示1
int hash[256]={0};
hash[str2[i]]++;
  1. 遍历第一个字符串str1,找到等于0的,需要保留的字符
    拿每一个字符,a对应的hash数组的97下标的值为0,表示a是想要的结果,保留;轮到b,b不为0,不是想要的结果,依次往后循环
  2. 最后输出acdf
注意

输入的字符串中间有空格隔开
cin >> str1;
cin >> str2;
不能这样写,cin遇到空格就结束了

#include <iostream>
#include <string>
using namespace std;

int main()
{
	//输入两个字符串
	string str1, str2;
	getline(cin, str1);
	getline(cin, str2);

	//创建哈希数组,用于记录字符串str2中每个字符的出现次数
	int hash[256] = {0};
	for(int i = 0; i < str2.size(); i++)
	{
		hash[str2[i]]++;
	}
	//创建结果字符串 ret,用于存储不在字符串str2中出现的字符
	string ret = "";
	for(int i = 0; i < str1.size(); i++)
	{
		if(hash[str1[i]] == 0)
		{
			ret += str1[i]; //每次将不在str2中出现的字符加入ret
		}
	}
	//输出结果字符串 ret
	cout << ret << endl;
	return 0;
}

这段代码的功能是找出两个输入字符串 str1str2 中,只在 str1 中出现而在 str2 中未出现的字符,并将其输出。代码通过创建一个大小为 256 的哈希数组 hash 来记录 str2 中每个字符的出现次数,然后遍历 str1,将不在 str2 中出现的字符添加到结果字符串 ret 中,最后输出 ret

  • 27
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值