面试的时候通常是acm模式,头文件用 #include<bits/stdc++.h>,做题就加一句using namespace std;
一.不含额外数据结构的输入输出
只需要cin,cout
这是最简单的也是大多数题用的,通过构建int,string并cin即可,遇到数组就用vector或者map去存
例子如下:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
vector<int> v;
int x;
int y;
cin>>n;
for(int i=0;i<n;i++){
int temp;
cin>>temp;
v.emplace_back(temp);
}
cin>>x>>y;
for(int i=0;i<v.size();i++){
if(v[i]==x){
if(i+1<int(v.size())&&v[i+1]==y){
cout<<"Yes"<<endl;
return 0;
}else{
cout<<"No"<<endl;
return 0;
}
}
if(v[i]==y){
if(i+1<int(v.size())&&v[i+1]==x){
cout<<"Yes"<<endl;
return 0;
}else{
cout<<"No"<<endl;
return 0;
}
}
}
return 0;
}
需要getline并且stringstream进行split的场景参见blog里面的《c++字符串分割&常见数据类型转换&进制转换》这篇文章
二.链表数据结构
自己写一个struct Node,然后当LeetCode题做,例子如下
#include<iostream>
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode(int val): val(val), next(nullptr) {}
};
ListNode* reverse (ListNode* head) {
ListNode* pre = nullptr;
ListNode* cur = head;
while (cur != nullptr) {
ListNode* tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
void printLinkedList(ListNode* head) {
ListNode* cur = head;
while (cur != nullptr) {
cout << cur->val << " ";
cur = cur->next;
}
cout << endl;
}
int main() {
int n, m;
ListNode* dummyHead = new ListNode(0);
while (cin >> n) {
if (n == 0) {
cout << "list is empty" << endl;
continue;
}
ListNode* cur = dummyHead;
// 读取输入构建链表
while (n--) {
cin >> m;
ListNode* newNode = new ListNode(m); // 构造节点
cur->next = newNode;
cur = cur->next;
}
printLinkedList(dummyHead->next);
printLinkedList(reverse(dummyHead->next));
}
return 0;
}
三.树数据结构
构建树有三种方式,一种是告诉你所有的边,一种是告诉你层序遍历结果,一种是告诉你前序遍历中序遍历让你序列化(LeetCode中等题889. 根据前序和后序遍历构造二叉树 - 力扣(LeetCode))(如果是二叉搜索树只需前序遍历就行1008. 前序遍历构造二叉搜索树 - 力扣(LeetCode))
通常一般就是前两种,示例代码如下:
//知道所有边
/*
输入示例
5
1 4
4 2
4 3
3 5
*/
#include<bits/stdc++.h>
using namespace std;
struct TreeNode{
int value;
vector<TreeNode*> childs;
TreeNode(int v):value(v){
};
TreeNode():value(0){
};
};
int main(){
unordered_map<int,TreeNode*> mp;
int n;
cin>>n;
for(int i=0;i<n-1;i++){
int value1;
int value2;
cin>>value1>>value2;
if(!mp.count(value1)){
TreeNode* node = new TreeNode(value1);
mp[value1] = node;
}
if(!mp.count(value2)){
TreeNode* node = new TreeNode(value2);
mp[value2] = node;
}
mp[value1]->childs.emplace_back(mp[value2]);
}
unordered_map<int,int> answer;
auto dfs = [&](auto &&dfs,TreeNode* root){
//cout<<"dfs:"<<root->value<<endl;
if(root->childs.size()==0){
answer[root->value]=1;
int m = root->value;
return m;
}
int minNode = root->childs[0]->value;
for(int i=0;i<root->childs.size();i++){
auto x = dfs(dfs,root->childs[i]);
minNode = min(minNode,x);
}
answer[root->value] = 1+answer[minNode];
//cout<<"here:"<<answer[root->value]<<endl;
return min(root->value,minNode);
};
dfs(dfs,mp[1]);
for(int i=1;i<=n;i++){
cout<<answer[i];
if(i!=n){
cout<<" ";
}
}
return 0;
}
//完全二叉树层次遍历可以用数组然后i*2,i*2+1为左右节点这么写
vector<TreeNode*> nodes(n+1);
for(int i=1;i<=n;i++){
TreeNode* node = new TreeNode();
nodes[i] = node;
}
for(int i=1;i<=n;i++){
string s;
cin>>s;
if(s=="null"){
nodes[i] = nullptr;
}else{
int temp = stoi(s);
nodes[i]->val = temp;
if(i*2<=n){
nodes[i]->left = nodes[i*2];
}
if(i*2+1<=n){
nodes[i]->right = nodes[i*2+1];
}
}
}
//层次遍历通用解法是用queue
#include<iostream>
#include<sstream>
#include<vector>
#include<string>
#include<queue>
using namespace std;
struct TreeNode {
TreeNode* left, *right;
int val;
TreeNode(int _val) : left(nullptr), right(nullptr), val(_val) {}
};
TreeNode *buildTree(vector<string>& nodes) {
if (nodes.empty() || nodes[0] == "null") return nullptr;
queue<TreeNode*> q;
TreeNode* root = new TreeNode(stoi(nodes[0]));
q.push(root);
int i = 1;
while (!q.empty() && i < nodes.size()) {
TreeNode* node = q.front();
q.pop();
if (i < nodes.size() && nodes[i] != "null") {
node->left = new TreeNode(stoi(nodes[i]));
q.push(node->left);
}
i++;
if (i < nodes.size() && nodes[i] != "null") {
node->right = new TreeNode(stoi(nodes[i]));
q.push(node->right);
}
i++;
}
return root;
}
int longest = 0;
int findPath(TreeNode* root) {
if (!root) return 0;
int left = findPath(root->left);
int right = findPath(root->right);
int leftPath = 0, rightPath = 0;
if (root->left && root->left->val == root->val) {
leftPath = left + 1;
}
if (root->right && root->right->val == root->val) {
rightPath = right + 1;
}
longest = max(longest, leftPath + rightPath);
return max(leftPath, rightPath);
}
int main() {
int n;
cin >> n;
cin.ignore();
string line;
getline(cin, line);
stringstream ss(line);
vector<string> nodes;
string node;
while (ss >> node) {
nodes.push_back(node);
}
TreeNode *root = buildTree(nodes);
findPath(root);
cout << longest << endl;
return 0;
}
四.字符串的坑
输入有空格或者分隔符的字符串时,如果知道每行的单词数量,那就可以按照数量cin到string中存入类似vector<string>的数组中,但有时候不知道数量时需要用getline(cin,s)读取一行放入s中,这时候有个cin和getline混用的坑
如下图所示,这是题目经常会碰到的情况,读取N行对每行进行处理,但是cin输入n之后,拿走的只是n的值,缓冲区还有个回车符\n,j结果缓冲区中的回车被getline()拿走
//错误写法
#include<iostream>
using namespace std;
int main(){
int N;
cin >> N ; //希望读取N行,并输出
while(N--){
string s;
getline(cin, s);
cout << s << endl;
}
}
因此当cin和getline混用的时候,在cin后面添加cin.ignore();忽略掉\n后再getline
//正确写法
#include<iostream>
using namespace std;
int main(){
int N;
cin >> N ;
cin.ignore(); // cin.ignore()可去除缓冲区中残留的'\n'.
while(N--){
string s;
getline(cin, s);
cout << s << endl;;
}
}
五.输出精度问题
如果遇到输出精度要求,比如double保留一位小数,那还是改用printf这个c语言函数吧(cout也能实现需要用std::cout << std::fixed << std::setprecision(1) << number << std::endl; 能记住最好有可能会忘记)
下面就是一个例子,输出的”%.1f”表示double保留一位小数
#include<bits/stdc++.h>
using namespace std;
int main(){
int num;
cin>>num;
cin.ignore();
string line;
getline(cin,line);
stringstream ss(line);
vector<pair<int,int>> v;
string split1;
while(getline(ss,split1,' ')){
stringstream ss2(split1);
string t1;
string t2;
getline(ss2,t1,':');
getline(ss2,t2,':');
v.push_back(make_pair(stoi(t1),stoi(t2)));
}
int n = v.size();
//两边特殊判断
if(num<v[0].first){
printf("%.1f", (double)v[0].second);
return 0;
}
if(num>v[n-1].first){
printf("%.1f", (double)v[n-1].second);
return 0;
}
for(int i=0;i<n-1;i++){
if(v[i].first<=num&&v[i+1].first>=num){
if(abs(v[i].first-num)<abs(v[i+1].first-num)){
printf("%.1f", (double)v[i].second);
return 0;
}else if(abs(v[i].first-num)>abs(v[i+1].first-num)){
printf("%.1f", (double)v[i+1].second);
return 0;
}else{
printf("%.1f", ((double)(v[i+1].second)+(double)(v[i].second))*0.5);
return 0;
}
}
}
return 0;
}