面试的时候通常是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;
}