技术标签: C++ c++ java 语言知识 面经 开发语言
大家好,这里是小黛~
三月开始,就会陆续开启各大公司暑期实习的笔试和面试,而笔试中,ACM模式是必须要去熟练掌握的,今天就来针对ACM模式进行详细介绍。
这个系列首先以C++为例,进行ACM模式的讲解,后续会补齐JAVA、GO、JS等常用语言的输入输出案例。
本文主要介绍五个方面:
第一是介绍核心代码模式和ACM模式,以及笔试面试的常见场景。
第二是介绍**C++**中常用的输入输出函数
第三是以笔试面试中常见的输入为例,进行代码层面的案例介绍。
第四是给出一些练习ACM模式的平台。
第五是把常见的数据结构定义,输入和输出展示出来,主要是链表和二叉树。
当我们刷算法题的时候,比如力扣、牛客这些网站,很多的题目只需要我们写出函数体(核心代码),平台就可以自动帮助我们补齐输入输出,进行调试,但,在笔试和面试中,往往需要自己写出可以运行的完整代码(ACM模式),这个时候,需要我们去了解一下自己所使用的语言下的输入输出如何去设计。
首先给出几个注意事项:
1.笔试平台用的比较多的,比如牛客,赛码,可以提前去熟悉熟悉上面的操作。
2.有些笔试,需要自己写输入输出,有些,则不需要,但我们必须要把输入输出搞懂,这样就不怕是什么类型的笔试了,而且输入输出本身是不难的,学习一下就可以完全掌握。最好不要出现,算法题的核心思路会写,卡在了输入输出上,这样就很难受了。
3.有些笔试,还会让大伙自己设计测试用例,这个平时练习的时候也可以注意一下,主要核心的思想就是测试用例设计的几个原则。
4.不仅仅是笔试,有些面试,也会要求你写输入输出和测试用例。
面试手撕代码的几种形式:
1.平台类
去面试官给定的平台上去面试,上面可以编写代码,调试和运行,这些平台有的写好了函数框架,有的是白板,需要自己写全部内容
2.自己的IDE
面试官要求候选人打开自己的ide,并共享桌面进行编写,这种肯定是要自己写全输入输出了
3.要求补齐测试用例
有些面试官,比如微软的面试官,可能会让你写完代码后,自己设计尽可能全面的测试用例,对你编写的代码进行测试。
C++的输入输出有很多种方式,既有继承自C语言的,也有其自己独特的。这里呢,不会把全部输入输出函数进行罗列,只会介绍几个在笔试面试中经常被用到的,我认为,掌握这几个足够了,如果有余力,可以去官方文档查看更多关于输入输出的函数进行深度学习。
首先,在C++语言中,要使用标准的输入,需要包含头文件<iostream>
cin是C++中, 标准的输入流对象,下面列出cin的两个用法,单独读入,和批量读入
cin的原理,简单来讲,是有一个缓冲区,我们键盘输入的数据,会先存到缓冲区中,用cin可以从缓冲区中读取数据。
注意1:cin可以连续从键盘读入数据
注意2:cin以空格、tab、换行符作为分隔符
注意3:cin从第一个非空格字符开始读取,直到遇到分隔符结束读取
示例:
// 用法1,读入单数据
int num;
cin >> num;
cout << num << endl; // 输出读入的整数num
// 用法2,批量读入多个数据
vector<int> nums(5);
for(int i = 0; i < nums.size(); i++) {
cin >> nums[i];
}
// 输出读入的数组
for(int i = 0; i < nums.size(); i++) {
cout << nums[i] << " ";
}
从cin的注意中,也可以看出,当我们要求读取的字符串中间存在空格的时候,cin会读取不全整个字符串,这个时候,可以采用getline()函数来解决。
注意1:使用getline()函数的时候,需要包含头文件
<string>
注意2:getline()函数会读取一行,读取的字符串包括空格,遇到换行符结束
示例:
string s;
getline(cin, s);
// 输出读入的字符串
cout << s << endl;
该函数会从缓存区中读出一个字符,经常被用于判断是否换行
示例:
char ch;
ch = getchar();
// 输出读入的字符
cout << ch << endl;
同样的,在C++语言中,要使用标准的输出,也需要包含头文件<iostream>
输出这边,主要介绍一个函数,就是用的最多的cout
,需要注意的是,如果输出endl
对象的时候,会输出一个换行符,类似\n
。
示例:
string s = "hello, Irray~";
// 看看二者有何不同
cout << "hello, Irray~";
cout << s << endl;
当然,C++中的输入输出函数不止这几个,其他的输入函数包括scanf()
,cin.get()
等等方式,输出函数也有printf()
,clog
,cerr
等方式,要根据具体的使用场景,选择具体的输入输出函数。
但,接下来的案例中,掌握上述三个方法是足够的。不想介绍太多,也是因为,记忆太多方法,容易记混,不如用最简洁的方式实现全部问题。
此类输入,每个元素为一个int或者char,有两类常见的案例:
3
1 2 3
or
3 1 2 3
对于第一组,第一行的3为整数的个数,第二行为三个用空格隔开的整数,因此可以采用cin
来进行读取
对于第二组,第一行的3为整数的个数,空格后面的数据为三个用空格隔开的整数,因此可以采用cin
来进行读取
此类问题,可以先创建一个vector<int>
,大小设置为给定值,然后通过for
循环来循环输入
int n;
cin >> n; // 读入3,说明数组的大小是3
vector<int> nums(n); // 创建大小为3的vector<int>
for(int i = 0; i < n; i++) {
cin >> nums[i];
}
// 验证是否读入成功
for(int i = 0; i < nums.size(); i++) {
cout << nums[i] << " ";
}
cout << endl;
1 2 3 4
输入的数据为四个用空格间隔的整数,没有指定整数个数,因此可以用while
循环结合cin
来处理该问题。
vector<int> nums;
int num;
while(cin >> num) {
nums.push_back(num);
// 读到换行符,终止循环
if(getchar() == '\n') {
break;
}
}
// 验证是否读入成功
for(int i = 0; i < nums.size(); i++) {
cout << nums[i] << " ";
}
cout << endl;
除了一维数组这种最基础的输入外,还会考察二维数组的输入,尤其是在dfs、dp类型的题目中。
二维数组主要有两种方式:
2 3
1 2 3
1 2 3
第一行的2,代表数据为2行,3代表数据为3列,因此根据第一行,可以得出,所输入数据为2行3列的二维数组。接下来的6个数字,就是按照空格和换行符分隔开的2x3二维数组,因此用for
循环和cin
即可处理
int m; // 接收行数
int n; // 接收列数
cin >> m >> n;
vector<vector<int>> matrix(m, vector<int>(n));
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
cin >> matrix[i][j];
}
}
// 验证是否读入成功
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
cout << matrix[i][j] << " ";
}
cout << endl;
}
2 3
1,2,3
1,2,3
第一行的2,代表数据为2行,3代表数据为3列,因此根据第一行,可以得出,所输入数据为2行3列的二维数组。接下来的2行,分别是一个字符串,字符串中用逗号隔开每个整数。这里采用读入字符串的方式,并将读入的字符串进行按逗号分开。
int m; // 接收行数
int n; // 接收列数
cin >> m >> n;
vector<vector<int>> matrix(m);
for(int i = 0; i < m; i++) {
// 读入字符串
string s;
getline(cin, s);
// 将读入的字符串按照逗号分隔为vector<int>
vector<int> vec;
int p = 0;
for(int q = 0; q < s.size(); q++) {
p = q;
while(s[p] != ',' && p < s.size()) {
p++;
}
string tmp = s.substr(q, p - q);
vec.push_back(stoi(tmp));
q = p;
}
//写入matrix
matrix[i] = vec;
vec.clear();
}
// 验证是否读入成功
for(int i = 0; i < matrix.size(); i++) {
for(int j = 0; j < matrix[i].size(); j++) {
cout << matrix[i][j] << " ";
}
cout << endl;
}
abc
用cin
读入即可
string s;
cin >> s;
// 验证是否读入成功
cout << s << endl;
3 abc ab a
第一行的3,代表有3个字符串,后续为用空格隔开的3个字符串,采用for
循环和cin
读入即可
int n;
cin >> n; // 读入3,说明字符串数组的大小是3
vector<string> strings(n); // 创建大小为3的vector<string>
for(int i = 0; i < n; i++) {
cin >> strings[i];
}
// 验证是否读入成功
for(int i = 0; i < strings.size(); i++) {
cout << strings[i] << " ";
}
cout << endl;
abc ab a d
输入为用空格隔开的若干个字符串。
vector<string> strings;
string str;
while(cin >> str) {
strings.push_back(str);
// 读到换行符,终止循环
if(getchar() == '\n') {
break;
}
}
// 验证是否读入成功
for(int i = 0; i < strings.size(); i++) {
cout << strings[i] << " ";
}
cout << endl;
11,22,3,4
输入为一个完整字符串,字符串内容是按照逗号隔开的一个数组,可以先读入完成字符串,然后根据逗号进行分隔
vector<int> vec;
// 读入字符串
string s;
getline(cin, s);
// 将读入的字符串按照逗号分隔为vector<int>
int p = 0;
for(int q = 0; q < s.size(); q++) {
p = q;
while(s[p] != ',' && p < s.size()) {
p++;
}
string tmp = s.substr(q, p - q);
vec.push_back(stoi(tmp));
q = p;
}
// 验证是否读入成功
for(int i = 0; i < vec.size(); i++) {
cout << vec[i] << " ";
}
cout << endl;
除了在笔试中实战之外,也可以在牛客平台进行练习:https://ac.nowcoder.com/acm/contest/5652
同时,牛客上也有很多专门的ACM模式算法题。
这里给出一个案例:
题目来源:https://ac.nowcoder.com/acm/contest/5652/A
**输入:**输入包括两个正整数a,b(1 <= a, b <= 1000),输入数据包括多组。
**输出:**输出a+b的结果
示例:
1)输入
1 5 10 20
2)输出
6 30
解答:
因为比较简单,就直接给出代码了。
#include <iostream>
using namespace std;
int main() {
int a;
int b;
while(cin >> a >> b) {
cout << a + b << endl;
}
return 0;
}
在ACM模式中,链表、二叉树这些数据结构的定义也需要自己去定义,接下来就给出二者的定义、输入和输出。
这里就直接给出代码了,想必大伙对数据结构都是了如指掌的。
#include <iostream>
using namespace std;
// 链表定义,并给出两个有参构造函数
struct ListNode
{
int val;
ListNode* next;
ListNode(int _val):val(_val),next(nullptr){}
ListNode(int _val,ListNode* _next):val(_val),next(_next){}
};
int main()
{
// 根据控制台的输入,创建一条单链表
ListNode* LHead = new ListNode(-1);
ListNode* pre = LHead;
ListNode* cur = nullptr;
int num;
while(cin >> num)
{
// 为了简单起见,设置为-1退出,后续可优化,这里只是给出一个例子
if(num == -1) break;
cur = new ListNode(num);
pre->next = cur;
pre = cur;
}
cur = LHead->next;
// 输出单链表的value
while(cur)
{
cout << cur->val << " ";
cur = cur->next;
}
cout << endl;
return 0;
}
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
//定义树节点
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode():val(0),left(nullptr),right(nullptr){}
TreeNode(int _val):val(_val),left(nullptr),right(nullptr){}
TreeNode(int _val,TreeNode* _left,TreeNode* _right):val(0),left(_left),right(_right){}
};
//根据数组生成树
TreeNode* buildTree(const vector<int>& v)
{
vector<TreeNode*> vTree(v.size(),nullptr);
TreeNode* root = nullptr;
for(int i = 0; i < v.size(); i++)
{
TreeNode* node = nullptr;
if(v[i] != -1)
{
node = new TreeNode(v[i]);
}
vTree[i] = node;
}
root = vTree[0];
for(int i = 0; 2 * i + 2 < v.size(); i++)
{
if(vTree[i] != nullptr)
{
vTree[i]->left = vTree[2 * i + 1];
vTree[i]->right = vTree[2 * i + 2];
}
}
return root;
}
//根据二叉树根节点层序遍历并打印
void printBinaryTree(TreeNode* root)
{
if(root == nullptr) return;
vector<vector<int>> ans;
queue<TreeNode*> q;
q.push(root);
while(!q.empty())
{
int size = q.size();
vector<int> path;
for(int i = 0;i<size;i++)
{
TreeNode* node = q.front();
q.pop();
if(node == nullptr)
{
path.push_back(-1);
}
else
{
path.push_back(node->val);
q.push(node->left);
q.push(node->right);
}
}
ans.push_back(path);
}
for(int i = 0;i<ans.size();i++)
{
for(int j = 0;j<ans[i].size();j++)
{
cout << ans[i][j] << " ";
}
cout << endl;
}
return;
}
int main()
{
// 验证
vector<int> v = {4,1,6,0,2,5,7,-1,-1,-1,3,-1,-1,-1,8};
TreeNode* root = buildTree(v);
printBinaryTree(root);
return 0;
}
欸嘿嘿,终于写完了!!!
本文内容干货非常非常多,从笔试面试环境的要点,到C++输入输出的具体函数,再到几乎覆盖全部情况的ACM模式写法,最后也给出了链表和二叉树的定义和输入输出。
全文代码都在本地IDE跑过,也都是本人今天亲手敲出来的,觉得有收获的可以点赞一波。
想和小黛一起交流的,也欢迎私聊,改简历、求职指导、模拟面试都是可以的哈~~~也有小窝,可以加我,我拉你哦
本人23年秋招拿了政策行总行、百度sp,美团,中国银行总行,中国银联总部等25个offer,非常欢迎小伙伴和我交流哇,改简历,学习计划,笔试面试经验,免费免费免费~~想来交流的随时私聊我哈
文章浏览阅读2.5w次,点赞6次,收藏50次。官方解释是,docker 容器是机器上的沙盒进程,它与主机上的所有其他进程隔离。所以容器只是操作系统中被隔离开来的一个进程,所谓的容器化,其实也只是对操作系统进行欺骗的一种语法糖。_docker菜鸟教程
文章浏览阅读5.7k次,点赞3次,收藏14次。该如何避免的,今天小编给大家推荐两个下载Windows系统官方软件的资源网站,可以杜绝软件捆绑等行为。该站提供了丰富的Windows官方技术资源,比较重要的有MSDN技术资源文档库、官方工具和资源、应用程序、开发人员工具(Visual Studio 、SQLServer等等)、系统镜像、设计人员工具等。总的来说,这两个都是非常优秀的Windows系统镜像资源站,提供了丰富的Windows系统镜像资源,并且保证了资源的纯净和安全性,有需要的朋友可以去了解一下。这个非常实用的资源网站的创建者是国内的一个网友。_msdn我告诉你
文章浏览阅读1.2k次。vue2封装对话框el-dialog组件_
文章浏览阅读4.7k次,点赞5次,收藏6次。MFC 文本框换行 标签: it mfc 文本框1.将Multiline属性设置为True2.换行是使用"\r\n" (宽字符串为L"\r\n")3.如果需要编辑并且按Enter键换行,还要将 Want Return 设置为 True4.如果需要垂直滚动条的话将Vertical Scroll属性设置为True,需要水平滚动条的话将Horizontal Scroll属性设_c++ mfc同一框内输入二行怎么换行
文章浏览阅读832次。检查Linux是否是否开启所需端口,默认为6379,若未打开,将其开启:以root用户执行iptables -I INPUT -p tcp --dport 6379 -j ACCEPT如果还是未能解决,修改redis.conf,修改主机地址:bind 192.168.85.**;然后使用该配置文件,重新启动Redis服务./redis-server redis.conf..._redis-server doesn't support auth command or ismisconfigured. try
文章浏览阅读4.9k次。济大数电实验报告_数据选择器及其应用
文章浏览阅读236次。1研究内容消费在生产中占据十分重要的地位,是生产的最终目的和动力,是保持省内经济稳定快速发展的核心要素。预测河南省社会消费品零售总额,是进行宏观经济调控和消费体制改变创新的基础,是河南省内人民对美好的全面和谐社会的追求的要求,保持河南省经济稳定和可持续发展具有重要意义。本文建立灰色预测模型,利用MATLAB软件,预测出2019年~2023年河南省社会消费品零售总额预测值分别为21881...._灰色预测模型用什么软件
文章浏览阅读1.2k次。12.4-在Qt中使用Log4Qt输出Log文件,看这一篇就足够了一、为啥要使用第三方Log库,而不用平台自带的Log库二、Log4j系列库的功能介绍与基本概念三、Log4Qt库的基本介绍四、将Log4qt组装成为一个单独模块五、使用配置文件的方式配置Log4Qt六、使用代码的方式配置Log4Qt七、在Qt工程中引入Log4Qt库模块的方法八、获取示例中的源代码一、为啥要使用第三方Log库,而不用平台自带的Log库首先要说明的是,在平时开发和调试中开发平台自带的“打印输出”已经足够了。但_log4qt
文章浏览阅读786次。全局观思维模型,一个教我们由点到线,由线到面,再由面到体,不断的放大格局去思考问题的思维模型。_计算机中对于全局观的
文章浏览阅读330次。一、CountDownLatch介绍CountDownLatch采用减法计算;是一个同步辅助工具类和CyclicBarrier类功能类似,允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。二、CountDownLatch俩种应用场景: 场景一:所有线程在等待开始信号(startSignal.await()),主流程发出开始信号通知,既执行startSignal.countDown()方法后;所有线程才开始执行;每个线程执行完发出做完信号,既执行do..._countdownluach于cyclicbarrier的用法
文章浏览阅读508次。Prometheus 算是一个全能型选手,原生支持容器监控,当然监控传统应用也不是吃干饭的,所以就是容器和非容器他都支持,所有的监控系统都具备这个流程,_-自动化监控系统prometheus&grafana实战
文章浏览阅读4.7k次。输入关键字,可以通过键盘的搜索按钮完成搜索功能。_react search