【Code Sprint】第一章 从零开始
✏️ 关于专栏:专栏用于记录prepare for the coding test.
文章目录
- 第一章 从零开始
- 1.输入输出技巧
- 常用输入输出加速
- 2.C++STL的使用
- unordered_map 和 unordered_set
- 3.多组输入的问题
第一章 从零开始
1.输入输出技巧
输入字符串数组
输入一行字符串带空格,使用scanf遇到空格会自动结束,使用gets不会结束。
#include<bits/stdc++.h>
using namespace std;
signed main(){string s; //int s[100][100];同理scanf("%s",s); printf("%s",s);return 0;
}
getchar:读取输入缓冲区的下一个字符(通常就是那个遗留的回车)。
字符的ASCII码—char字符和int值是可以相互转化的
printf("%d\n",'a'); //97
printf("%d\n",'A'); //65
关于换行符处理的一个eg~
//存储地图
/*** #####.####@##### ***/
//1.正确做法
#include<bits/stdc++.h>
using namespace std;
char grid[10][10];
signed main(){for(int i = 1;i <= 4;i++){for(int j = 1;j <= 4;j++){cin>>grid[i][j];}}for(int i = 1;i <= 4;i++){for(int j = 1;j <= 4;j++){cout<<grid[i][j];}cout<<endl;}return 0;
}#include<bits/stdc++.h>
using namespace std;
char grid[10][10];
signed main(){for(int i = 1;i <= 4;i++){scanf("%s",grid[i]+1); //代表此行的第1列(从第0列开始) }for(int i = 1;i <= 4;i++){for(int j = 1;j <= 4;j++){cout<<grid[i][j];}cout<<endl;}return 0;
}
//2.错误做法
#include<bits/stdc++.h>
using namespace std;
char grid[10][10];
signed main(){for(int i = 1;i <= 4;i++){for(int j = 1;j <= 4;j++){scanf("%c",&grid[i][j]);}}for(int i = 1;i <= 4;i++){for(int j = 1;j <= 4;j++){cout<<grid[i][j];}cout<<endl;}return 0;
}
小结:cin本身就会自动跳过空白符(空格、回车、Tab)
scanf是原样读取,不会跳过空白,会把回车读进变量
常用输入输出加速
在大数据量输入输出时,可以使用以下方法加速C++读写:
#include<bits/stdc++.h>
using namespace std;
signed main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int n;cin >> n;cout << n << endl;return 0;
}
ios::sync_with_stdio(false)
:取消cin和scanf同步,加速cincin.tie(0)
:取消cin和cout绑定,加速cincout.tie(0)
:取消cout与cin的刷新绑定,加速cout- 注意:使用这些后,cin和scanf不要混用,统一用cin/cout。
2.C++STL的使用
sort()函数,依次传入三个参数,要排序区间的起点,要排序区间的终点+1,比较函数。比较函数可以不填,则默认从小到大排序。
#include<bits/stdc++.h>
using namespace std;
int a[105];
signed main(){int n;cin>>n;for(int i = 0;i < n;i++){cin>>a[i];}sort(a,&a[n]);//这里用sort(a,a+n);也是可以的for(int i = 0;i < n;i++){cout<<a[i]<<" ";}return 0;
}
从小到大的排序数组中
lower_bound(begin,end,num)函数:从数组的 begin 位置到 end-1 位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin, 得到找到数字在数组中的下标。
upper_bound(begin,end,num)函数:从数组的 begin 位置到 end-1 位置二分查找第一个大于 num的数字,找到返回该数字的地址,不存在则返回 end。通过返回的地址减去起始地址 begin, 得到找到数字在数组中的下标。
从大到小的排序数组中
lower_bound(begin,end,num,greater())函数:从数组的 begin 位置到 end-1 位置二分查找第一个小于或等于 num 的数字,找到返回该数字的地址,不存在则返回 end。通过返回的地址减去起始地址 begin,得到找到数字在数组中的下标。
upper_bound(begin,end,num,greater())函数:从数组的 begin 位置到 end-1 位置二分查找第一个小于 num 的数字,找到返回该数字的地址,不存在则返回 end。通过返回的地址减去起始地址 begin,得到找到数字在数组中的下标。
#include<bits/stdc++.h>
using namespace std;
int cmp(int a,int b){return a>b;
}
signed main(){int nums[6]={1,2,4,7,15,34};sort(nums,nums+6);int pos1=lower_bound(nums,nums+6,7) - nums;int pos2=upper_bound(nums,nums+6,7) - nums;//返回数组中第一个大于被查数的值cout<<pos1<<" "<<nums[pos1]<<endl;cout<<pos2<<" "<<nums[pos2]<<endl;sort(nums,nums+6,greater<int>());int pos3=lower_bound(nums,nums+6,7,greater<int>()) - nums;int pos4=upper_bound(nums,nums+6,7,greater<int>()) - nums;cout<<pos3<<" "<<nums[pos3]<<endl;cout<<pos4<<" "<<nums[pos4]<<endl;return 0;
}
string(虽然不属于,但有很多相似之处)
#include<bits/stdc++.h>
using namespace std;
signed main(){string s = "abcdefg";cout << s.length() << endl; //长度cout << s.substr(1,3) << endl; //从下标1开始取3个字符s.insert(2, "XYZ"); //在第2个位置插入字符串cout << s << endl;s.erase(2,3); //从第2个位置删除3个字符cout << s << endl;cout << s.find("de") << endl; //查找子串cout << (s == "abcdefg") << endl; //字符串比较reverse(s.begin(),s.end()); //字符串反转cout << s << endl;return 0;
}
方法 | 作用 |
---|---|
s.length() | 返回字符串长度 |
s.substr(pos, len) | 返回从pos开始长len的子串 |
s.insert(pos, str) | 在pos插入字符串 |
s.erase(pos, len) | 从pos开始删除len个字符 |
s.find(str) | 找到子串第一次出现的位置 |
reverse(s.begin(), s.end()) | 字符串反转 |
pair
#include<bits/stdc++.h>
using namespace std;
signed main(){pair<int,string> p;p = {1,"apple"};cout<<p.first<<" "<<p.second<<endl;vector<pair<int,int>> vp;vp.push_back({2,3});vp.push_back({4,1});sort(vp.begin(), vp.end()); //pair默认按first排序,相同first按secondfor(auto pr : vp){cout<<pr.first<<" "<<pr.second<<endl;}return 0;
}
priority_queue
- 大根堆
- 小根堆
- 自定义
#include<bits/stdc++.h>
using namespace std;
struct Node{int value;int priority;
};
struct cmp{bool operator()(Node a,Node b){return a.priority < b.priority;}
};
signed main(){priority_queue<int> maxHeap;//大根堆 maxHeap.push(1);maxHeap.push(2);maxHeap.push(3);while(!maxHeap.empty()){cout<<maxHeap.top()<<endl;maxHeap.pop();}priority_queue<int,vector<int>,greater<int>> minHeap;minHeap.push(1);minHeap.push(2);minHeap.push(3);while(!minHeap.empty()){cout<<minHeap.top()<<endl;minHeap.pop();}priority_queue<Node,vector<Node>,cmp> dmaxHeap;dmaxHeap.push({1,1});dmaxHeap.push({2,2});dmaxHeap.push({3,3});while(!dmaxHeap.empty()){cout<<dmaxHeap.top().value<<" "<<dmaxHeap.top().priority<<endl;dmaxHeap.pop();}return 0;
}
vector
动态数组,最常用容器之一。
- 常用操作总结表:
操作 | 语法 |
---|---|
添加元素 | v.push_back(x) |
删除末尾元素 | v.pop_back() |
访问元素 | v[i] 或 v.at(i) |
插入元素 | v.insert(v.begin()+pos, x) |
删除元素 | v.erase(v.begin()+pos) |
大小 | v.size() |
清空 | v.clear() |
排序 | sort(v.begin(), v.end()) |
反转 | reverse(v.begin(), v.end()) |
#include<bits/stdc++.h>
using namespace std;
signed main(){vector<int> nums;for(int i = 1;i <= 10;i++){nums.push_back(i*i);}for(int i = 0;i < nums.size();i++){cout<<nums[i]<<" ";}cout<<endl;return 0;
}
queue
先进先出(FIFO)
#include<bits/stdc++.h>
using namespace std;
signed main(){queue<int>q;q.push(1);q.push(2);q.push(3);while(!q.empty()){cout<<q.front()<<endl;//cout<<q.back()<<endl;队列尾部元素 q.pop();} return 0;
}
stack
后进先出(LIFO)
#include<bits/stdc++.h>
using namespace std;
signed main(){stack<int>s;s.push(1);s.push(2);s.push(3);while(!s.empty()){cout<<s.top()<<endl;s.pop();} return 0;
}
map
键值对集合,自动按key升序排序
#include<bits/stdc++.h>
using namespace std;
signed main(){map<string,int> dict;dict["Tom"] = 1;dict["Jone"] = 2;dict["Mary"] = 1;if (dict.count("Mary")) {//查找 mapcout<<"Mary is in class "<<dict["Mary"]<<endl;}for(map<string,int>::iterator it = dict.begin();it!=dict.end();it++){cout<<it->first<<" "<<it->second<<endl;}dict.clear();return 0;
}
set
集合,自动去重且按升序排列
#include<bits/stdc++.h>
using namespace std;
signed main(){set<string> country;country.insert("China");country.insert("American");country.insert("France");set<string>::iterator it;for(it = country.begin();it != country.end();it++){cout<<*it<<" ";}cout<<endl;country.erase("American");country.erase("France");country.clear();return 0;
}
unordered_map 和 unordered_set
无序版的map和set,底层哈希表,查找效率更高(平均O(1)),但不保证元素顺序。
✨ 特别小结:
容器 | 特点 |
---|---|
vector | 动态数组 |
stack | 栈(后进先出) |
queue | 队列(先进先出) |
priority_queue | 优先队列(大/小根堆) |
map | 有序映射(自动排序) |
set | 有序去重集合 |
unordered_map | 无序哈希映射 |
unordered_set | 无序哈希集合 |

3.多组输入的问题
多组输入一定要注意初始化问题,数组和变量的初始化要放在 while 循环内,否则上一次的运算的结果会影响当前的结果。
#include<bits/stdc++.h>
using namespace std;
signed main(){int a,b;while(cin>>a>>b){cout<<a+b<<endl;}return 0;
}