🎇C++笔试强训
- 博客主页:一起去看日落吗
- 分享博主的C++刷题日常,大家一起学习
博主的能力有限,出现错误希望大家不吝赐教
- 分享给大家一句我很喜欢的话:夜色难免微凉,前方必有曙光 🌞。
💦🔥
选择题
💦 第一题
下面的程序执行输出几个hello?
#include<stdio.h>
#include <unistd.h>
int main( ) {
fork( );
fork( );
fork( );
printf(“hello\n”);
return 0;
}
A 3
B 4
C 6
D 8
这道题的答案是D
💦 第二题
有一个程序中有A,B,C三个线程同时对一个文件进行读写操作,其中的A,B是写进程只负责往里面写数据,C是读线程,同时把读取的数据从文件中删除,A线程单独写满文件需要10个小时,B单独写程序需要6小时,C线程需要15小时才能读取完整个文件,不考虑三个线程之间的相互影响的情况下现在____小时才能写满文件
A 5
B 6
C 5.5
D 4.5
E 4.8
F 5.3
这道题的答案是A
💦 第三题
系统中内存不足程序所需大小,程序就无法执行。
A 错
B 对
操作系统存在虚拟内存,能够把一部分优先级较低的程序保存到系统硬盘
这道题的答案是A
💦 第四题
通常所说的"存储保护"的基本含义是()
A 防止存储器硬件受损
B 防止程序在内存丢失
C 防止程序间相互越界访问
D 防止程序被人偷看
这道题的答案是C
💦 第五题
下列进程调度算法中,()可能会出现进程长期得不到调度的情况。
A 非强占式静态优先权法
B 强占式静态优先权法
C 时间片轮转调度算法
D 非强占式动态优先权法
这道题的答案是B
💦 第六题
如果信号量的当前值为-4,则表示系统中在该信号量上有()个进程等待。
A 4
B 3
C 5
D 0
这道题的答案是A
💦 第七题
设两个进程共用一个临界资源的互斥信号量mutex=1,当mutex=-1时表示()
A 一个进程进入了临界区,另一个进程等待
B 没有一个进程进入临界区
C 两个进程都进入临界区
D 两个进程都在等待
这道题的答案是A
💦 第八题
若系统中只有用户级线程,则处理机调度单位是()
A 线程
B 进程
C 程序
D 作业
这道题的答案是B
💦 第九题
一个在线服务器通常需要读取存储着海量数据的数据库。为了提高服务器处理速度,通常需要加cache(缓存),以下场景中不适合使用cache的是()
A 数据库中每条数据被访问的概率近似相等,且独立
B 使用了多线程机制的服务
C 单条线程尺寸太小的数据
D 有着大量访问的服务
这道题的答案是A
💦 第十题
计算机操作系统的主要功能是( )
A 管理计算机系统的软硬件资源,以充分发挥计算机资源的效率,并为其它软件提供良好的运行环境
B 把高级程序设计语言和汇编语言编写的程序翻译到计算机硬件可以直接执行的目标程序,为用户提供良好的软件开发环境
C 对各类计算机文件进行有效的管理,并提交计算机硬件高效处理
D 为用户提供方便地操作和使用计算机
这道题的答案是A
编程题
🔥 第一题
链接:反转部分单链表
- 解题思路一
找到需要反转部分链表的起始位置,断链反转之后,再进行恢复链表输出.
- 图解
双指针反转链表过程:
- 代码演示
# include <bits/stdc++.h>
using namespace std;
struct list_node{
int val;
struct list_node * next;
};
list_node * input_list(void)
{
int n, val;
list_node * phead = new list_node();
list_node * cur_pnode = phead;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &val);
if (i == 1) {
cur_pnode->val = val;
cur_pnode->next = NULL;
}
else {
list_node * new_pnode = new list_node();
new_pnode->val = val;
new_pnode->next = NULL;
cur_pnode->next = new_pnode;
cur_pnode = new_pnode;
}
}
return phead;
}
list_node* ReveserList(list_node* RHead)
{
list_node* prev = nullptr;
list_node* cur = RHead;
while(cur)
{
list_node* next = cur->next;
//反转
cur->next = prev;
//更新prev和cur,继续向后迭代反转
prev = cur;
cur = next;
}
return prev;
}
list_node * reverse_list(list_node * head, int L, int R)
{
//先创建一个虚拟头节点
list_node* pHead = new list_node;
pHead->next = head;
list_node* prevNode = pHead;
list_node* RHead = nullptr;
list_node* RTail = nullptr;
list_node* nextNode = nullptr;
//找到反转部分链表的前一个节点
for(int i = 0;i < L-1;i++)
{
prevNode = prevNode->next;
}
RHead = prevNode->next;
//找到反转链表的尾节点
RTail = RHead;
for(int i = 0;i < R-L;i++)
{
RTail = RTail->next;
}
nextNode = RTail->next;
//需要将RTail->next = nullptr;
RTail->next = nullptr;
list_node* newHead = ReveserList(RHead);
//恢复链接
prevNode->next = newHead;
RHead->next = nextNode;
list_node* list = pHead->next;
delete pHead;
return list;
}
void print_list(list_node * head)
{
while (head != NULL) {
printf("%d ", head->val);
head = head->next;
}
puts("");
}
int main ()
{
int L, R;
list_node * head = input_list();
scanf("%d%d", &L, &R);
list_node * new_head = reverse_list(head, L, R);
print_list(new_head);
return 0;
}
- 解题思路二
思路一的弊端:假设需要反转的链表部分,占比比较大,则需要两次遍历链表来实现. (1.遍历确定反转链表的起始
位置 2.遍历链表进行反转). 那是不是可以考虑一次遍历链表就解决该问题呢?
这里的思路是:采用头插的方式一次遍历解决问题
- 图解
- 代码演示
# include <bits/stdc++.h>
using namespace std;
struct list_node{
int val;
struct list_node * next;
};
list_node * input_list(void)
{
int n, val;
list_node * phead = new list_node();
list_node * cur_pnode = phead;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &val);
if (i == 1) {
cur_pnode->val = val;
cur_pnode->next = NULL;
}
else {
list_node * new_pnode = new list_node();
new_pnode->val = val;
new_pnode->next = NULL;
cur_pnode->next = new_pnode;
cur_pnode = new_pnode;
}
}
return phead;
}
list_node * reverse_list(list_node * head, int L, int R)
{
//创建虚拟头节点
list_node* pHead = new list_node;
pHead->next = head;
list_node* prevNode = pHead;
for(int i = 0;i < L-1;i++)
{
prevNode = prevNode->next;
}
list_node* cur = prevNode->next;
for(int i = 0;i < R-L;i++)
{
list_node* curNextNode = cur->next;
cur->next = curNextNode->next;//先进行链接,防止后面的断链
//头插
curNextNode->next = prevNode->next;
prevNode->next = curNextNode;
}
list_node* list = pHead->next;
delete pHead;
return list;
}
void print_list(list_node * head)
{
while (head != NULL) {
printf("%d ", head->val);
head = head->next;
}
puts("");
}
int main ()
{
int L, R;
list_node * head = input_list();
scanf("%d%d", &L, &R);
list_node * new_head = reverse_list(head, L, R);
print_list(new_head);
return 0;
}
🔥 第二题
链接:猴子分桃
- 解题思路
因为每次分5堆都会多出来1个,所以我们借给猴子们4个,以致每次都可以刚好分成5堆 并且,每次给老猴子的桃
子都不在我们借出的那4个中,这样最后减掉4就可以得到结果。 假设最初由x个桃子,我们借给猴子4个,则此时
有x+4个, 第一个猴子得到(x+4)/5,剩余(x+4)(4/5)个 第二个猴子分完后剩余(x+4) (4/5)^2个 第三个
猴子分完后剩余(x+4) (4/5)^3个 依次类推,第n个猴子分完后剩余(x+4)(4/5)^n 要满足最后剩余的为整
数,并且x最小,则当 x+4=5n时,满足要求;此时,x=5n - 4; 老猴子得到的数量为:x+4)*(4/5)^n + n - 4
= 4^n + n - 4 最后的 +n是因为每个小猴子都会多出一个给老猴子,-4是还了借的4个
- 代码演示
// write your code here cpp
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int n;
while(cin >> n)
{
if(n == 0)
break;
long total = pow(5,n) - 4;
long left = pow(4,n) + n - 4;
cout << total << " " << left << endl;
}
return 0;
}