2021算法笔记Codeup、pat刷题记录
目录
- 《算法笔记》6.1小节——C++标准模板库(STL)介绍->vector的常见用法详解
- 《算法笔记》6.2小节——C++标准模板库(STL)介绍->set的常见用法详解
- 《算法笔记》6.3小节——C++标准模板库(STL)介绍->string的常见用法详解
- 《算法笔记》6.5小节——C++标准模板库(STL)介绍->queue的常见用法详解
- 《算法笔记》6.7小节——C++标准模板库(STL)介绍->stack的常见用法详解
- 《算法笔记》6.8小节——C++标准模板库(STL)介绍->pair的常见用法详解
- 《算法笔记》6.9小节——C++标准模板库(STL)介绍->algorithm头文件下常用函数介绍
《算法笔记》6.1小节——C++标准模板库(STL)介绍->vector的常见用法详解
Course List for Student (25)
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 26 * 26 * 26 * 10 + 1;//hash表的上界
vector<int> studentinfo[N];
int getID(char name[]) {//使用字符串哈希,将学生名与数字一一对应
int id = 0;
for (int i = 0;i < 3;++i) {
id = id * 26 + name[i] - 'A';
}
id = id * 10 + name[3] - '0';
return id;
}
int main() {
int n, k;
char name[5];
scanf("%d %d", &n, &k);
for (int i = 0;i < k;++i) {
int course, x;
scanf("%d %d", &course, &x);
for (int j = 0;j < x;++j) {
scanf("%s", name);
int id = getID(name);
studentinfo[id].push_back(course);
}
}
for (int i = 0;i < n;++i) {
scanf("%s", name);
int id = getID(name);
printf("%s %d", name, studentinfo[id].size());
sort(studentinfo[id].begin(), studentinfo[id].end());
for (int j = 0;j < studentinfo[id].size();++j) {
printf(" %d", studentinfo[id][j]);
}
printf("\n");
}
return 0;
}
Student List for Course (25)
用string写的,Codeup能过,PTA最后一个测试点会超时
#include<cstdio>
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
const int maxK = 2510;
vector<string> studentList[maxK];
int main() {
int n, k;
scanf("%d %d", &n, &k);
for (int i = 0;i < n;++i) {
int m;
string name;
cin >> name >> m;
while (m--) {
int temp;
scanf("%d", &temp);
studentList[temp].push_back(name);
}
}
for (int i = 1;i <= k;++i) {
printf("%d %d\n", i, studentList[i].size());
sort(studentList[i].begin(), studentList[i].end());
for (int j = 0;j < studentList[i].size();++j) {
cout << studentList[i][j] << endl;
}
}
return 0;
}
使用printf输出最后一个测试点的时间达到417 ms,这是晴神笔记上的代码思路,用char name[maxn][5]
数组存放学生姓名,并且cmp函数中使用姓名对vector中的数字进行排序,这种想法很精妙。
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 40010;
const int maxk = 2510;
char name[maxn][5];
vector<int> course[maxk];
bool cmp(int a, int b) {//排序改变vector中的数字顺序,而不用改变数组中字符串的顺序,太妙了
return strcmp(name[a], name[b]) < 0;
}
int main() {
int n, k;
scanf("%d %d", &n, &k);
for (int i = 0;i < n;++i) {
int m;
scanf("%s %d", name[i], &m);
for (int j = 0;j < m;++j) {
int temp;
scanf("%d", &temp);
course[temp].push_back(i);
}
}
for (int i = 1;i <= k;++i) {
printf("%d %d\n", i, course[i].size());
sort(course[i].begin(), course[i].end(), cmp);
for (int j = 0;j < course[i].size();++j) {
printf("%s\n", name[course[i][j]]);//name[course[i][j]]易错
}
}
return 0;
}
《算法笔记》6.2小节——C++标准模板库(STL)介绍->set的常见用法详解
Set Similarity (25)
set是内部自动升序,且无重复元素的容器。
#include<cstdio>
#include<set>
using namespace std;
set<int> st[55];
void compare(int a, int b) {
int sameNum = 0, allNum = st[b].size();//注意这里的初始值
for (set<int>::iterator it = st[a].begin();it != st[a].end();++it) {
if (st[b].find(*it) != st[b].end()) ++sameNum;
else ++allNum;
}
printf("%.1f%%\n", 100.0 * sameNum / allNum);
}
int main() {
int n;
scanf("%d", &n);
for (int i = 1;i <= n;++i) {
int m;
scanf("%d", &m);
while (m--) {
int t;
scanf("%d", &t);
st[i].insert(t);
}
}
int k;
scanf("%d", &k);
while (k--) {
int a, b;
scanf("%d %d", &a, &b);
compare(a, b);
}
return 0;
}
《算法笔记》6.3小节——C++标准模板库(STL)介绍->string的常见用法详解
Codeup
字符串处理
额,相信了网上的正确答案,结果写完发现人家的也不能AC。。。自己这个问题也有点大,测试了一下如果小数部分算出来最大位是0的话,0是会输出不了的例如1563.123+18564.22,总是就是错了。问题很多
#include<cstring>
#include<iostream>
#include<string>
using namespace std;
long long to_num(string s, int& e) {
int flag = 1, bflag = 1, len = s.length(), f = 0;
long long num = 0;
for (int i = 0;i < len;++i) {
if (s[i] == '-') flag = -1;//碰到负号将flag变为-1;
else if (s[i] == '.') f = 1;//s是浮点数;
else if (s[i] == 'e' || s[i] == 'E') {//碰到e,E后面的指数
++i;
if (s[i] == '-') {//指数是负的情况
bflag = -1;
++i;
}
int temp = 0;
while (i < s.length()) {
temp = 10 * temp + s[i] - '0';
++i;
}
e += temp * bflag;//指数加上E后指数
}
else {
num = 10 * num + s[i] - '0';
e -= f;//如果有.则每次遍历需要使指数-1
}
}
num *= flag;
return num;
}
int main() {
string a, b;
while (cin >> a >> b) {
int e1 = 0, e2 = 0;
long long numa = to_num(a, e1), numb = to_num(b, e2);
if (e1 < e2) {
while (e1 < e2) {
numb *= 10;
--e2;
}
}
else {
while (e1 > e2) {
numa *= 10;
--e1;
}
}
// printf("%lld %d %lld %d\n",numa,e1,numb,e2);
long long num = numa + numb;
int e = e1, d = 1, m = 0;
for (long long i = num;i > 10;i /= 10) {
d *= 10;
++m;
}
// printf("%d %d\n",d,m);
printf("%lld", num / d);
printf(".%lld", num % d);
printf("e%d\n", e1 + m);
}
return 0;
}
配套实战指南
PAT A1060 Are They Equal
#include<iostream>
#include<string>
using namespace std;
int n;
string change(string s, int& e) {
int k = 0;
while (s.length() > 0 && s[0] == '0') {
s.erase(s.begin());
}
if (s[0] == '.') {
s.erase(s.begin());
while (s.length() > 0 && s[0] == '0') {
s.erase(s.begin());
--e;
}
}
else {
while (s[k] != '.' && k < s.length()) {
++e;
++k;
}
if (k < s.length()) s.erase(s.begin() + k);
}
if (s.length() == 0) e = 0;
string res;
int num = 0;
k = 0;
while (num < n) {
if (k < s.length()) res += s[k++];
else res += '0';
++num;
}
return res;
}
int main() {
string str1, str2;
cin >> n >> str1 >> str2;
int e1 = 0, e2 = 0;
str1 = change(str1, e1);
str2 = change(str2, e2);
if (str1 == str2 && e1 == e2) cout << "YES 0." << str1 << "*10^" << e1 << endl;
else cout << "NO 0." << str1 << "*10^" << e1 << " 0." << str2 << "*10^" << e2 << endl;
return 0;
}
PAT A1100 Mars Numbers/
#include<cstdio>
#include<iostream>
#include<map>
#include<string>
using namespace std;
string unitDigit[13] = { "tret","jan","feb","mar","apr","may","jun","jly","aug","sep","oct","nov","dec" };
string tenDigit[13] = { "tret","tam","hel","maa","huh","tou","kes","hei","elo","syy","lok","mer","jou" };
string numToStr[170];
map<string, int> strToNum;
void init() {
for (int i = 0;i < 13;++i) {//对十位为0和百位为零的数赋值
numToStr[i] = unitDigit[i];
strToNum[unitDigit[i]] = i;
numToStr[13 * i] = tenDigit[i];
strToNum[tenDigit[i]] = 13 * i;
}
for (int i = 1;i < 13;++i) {//对普通数赋值
for (int j = 1;j < 13;++j) {
string temps = tenDigit[i] + " " + unitDigit[j];
numToStr[13 * i + j] = temps;
strToNum[temps] = 13 * i + j;
}
}
}
int main() {
init();
int n;
scanf("%d", &n);
getchar();//吸收回车键
while (n--) {
string str;
getline(cin, str);
int num = 0;
if (str[0] >= '0' && str[0] <= '9') {
for (int i = 0;i < str.size();++i) {
num = num * 10 + str[i] - '0';
}
cout << numToStr[num] << endl;
}
else {
cout << strToNum[str] << endl;
}
}
return 0;
}
PAT A1054 The Dominant Color
map写法
#include<cstdio>
#include<map>
using namespace std;
int main() {
int m, n;
scanf("%d %d", &m, &n);
n = m * n;
map<int, int> count;
for (int i = 0;i < n;++i) {
int color;
scanf("%d", &color);
if (count.find(color) != count.end()) ++count[color];
else count[color] = 1;
}
int k = 0, max = -1;
for (map<int, int>::iterator it = count.begin();it != count.end();++it) {
if (it->second > max) {
k = it->first;
max = it->second;
}
}
printf("%d\n", k);
return 0;
}
笔试题写法
#include<cstdio>
int main() {
int m, n, ans, cnt = 0;
scanf("%d %d", &m, &n);
n = m * n;
for (int i = 0;i < n;++i) {
int color;
scanf("%d", &color);
if (color != ans) {//超过半数的数一定会留下
if (cnt == 0) {
ans = color;
cnt = 1;
}
else --cnt;
}
else ++cnt;
}
printf("%d\n", ans);
return 0;
}
PAT A1071 Speech Patterns
#include<string>
#include<iostream>
#include<map>
using namespace std;
bool valid(char c) {
if (c >= '0' && c <= '9') return true;
else if (c >= 'A' && c <= 'Z') return true;
else if (c >= 'a' && c <= 'z') return true;
return false;
}
int main() {
string sen, word;
getline(cin, sen);
map<string, int> count;
for (int i = 0;i < sen.size();) {
while (i < sen.length() && valid(sen[i])) {
if (sen[i] >= 'A' && sen[i] <= 'Z') sen[i] += 32;
word += sen[i];
++i;
}
if (word.length() > 0) {
if (count.find(word) == count.end()) count[word] = 1;
else ++count[word];
word.clear();
}
while (i < sen.length() && valid(sen[i]) == false) ++i;
}
string ans;
int max = 0;
for (map<string, int>::iterator it = count.begin();it != count.end();++it) {
if (it->second > max) {
ans = it->first;
max = it->second;
}
}
cout << ans << " " << max << endl;
return 0;
}
PAT A1022 Digital Library
#include<cstdio>
#include<string>
#include<iostream>
#include<map>
#include<set>
using namespace std;
map<string, set<int> > mpTitle, mpAuthor, mpKey, mpPub, mpYear;
void query(map<string, set<int> >& mp, string& str) {
if (mp.find(str) == mp.end()) printf("Not Found\n");
else {
for (set<int>::iterator it = mp[str].begin();it != mp[str].end();++it) {
printf("%07d\n", *it);
}
}
}
int main() {
int n;
scanf("%d", &n);
while (n--) {
int IDnum;
scanf("%d", &IDnum);
getchar();
string title, author, key, pub, year;
getline(cin, title);
mpTitle[title].insert(IDnum);
getline(cin, author);
mpAuthor[author].insert(IDnum);
while (cin >> key) {
mpKey[key].insert(IDnum);
char c = getchar();
if (c == '\n') break;
}
getline(cin, pub);
mpPub[pub].insert(IDnum);
getline(cin, year);
mpYear[year].insert(IDnum);
}
scanf("%d", &n);
getchar();
for (int i = 0;i < n;++i) {
string str, head;
getline(cin, str);
int m = str[0] - '0';
cout << str << endl;
str.erase(0, 3);
switch (m) {
case 1: {
query(mpTitle, str);
break;
}
case 2: {
query(mpAuthor, str);
break;
}
case 3: {
query(mpKey, str);
break;
}
case 4: {
query(mpPub, str);
break;
}
case 5: {
query(mpYear, str);
break;
}
}
}
return 0;
}
《算法笔记》6.5小节——C++标准模板库(STL)介绍->queue的常见用法详解
C语言-数字交换
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
void scan(vector<int> &vi){
int n;
for(int i=0;i<10;++i){
scanf("%d",&n);
vi.push_back(n);
}
}
void change(vector<int> &vi){
int min=100000,max=-1,minn=0,maxn=0;
for(int i=0;i<10;++i){
if(min>vi[i]){
min=vi[i];
minn=i;
}
}
swap(vi[minn],vi[0]);
for(int i=0;i<10;++i){
if(max<vi[i]){
max=vi[i];
maxn=i;
}
}
swap(vi[maxn],vi[9]);
}
void print(vector<int> vi){
for(int i=0;i<10;++i) printf("%d ",vi[i]);
}
int main(){
vector<int> vi;
scan(vi);
change(vi);
print(vi);
return 0;
}
《算法笔记》6.7小节——C++标准模板库(STL)介绍->stack的常见用法详解
简单计算器
#include<iostream>
#include<cstdio>
#include<string>
#include<map>
#include<stack>
#include<queue>
using namespace std;
struct node {
double num;//操作数
char op;//操作符
bool flag;//ture 表示操作数,false表示操作符
};
string str;
stack<node> s;
queue<node> q;
map<char, int> mp;
void change() {//将中缀表达式转换成后缀
node temp;
for (int i = 0;i < str.length();) {
if (str[i] >= '0' && str[i] <= '9') {
temp.flag = true;
temp.num = str[i++] - '0';
while (i < str.length() && str[i] >= '0' && str[i] <= '9') {
temp.num = 10 * temp.num + str[i] - '0';
++i;
}
q.push(temp);
}
else {
temp.flag = false;
while (!s.empty() && mp[str[i]] <= mp[s.top().op]) {
q.push(s.top());
s.pop();
}
temp.op = str[i];
s.push(temp);
++i;
}
}
while (!s.empty()) {
q.push(s.top());
s.pop();
}
}
double calculate() {
node cur;
while (!q.empty()) {
cur = q.front();
q.pop();
if (cur.flag == true) s.push(cur);//如果是数,则压入栈中
else {//为操作符则拿出前两个数进行计算
node temp;
temp.flag = true;
double temp1, temp2;
temp2 = s.top().num;
s.pop();
temp1 = s.top().num;
s.pop();
if (cur.op == '+') temp.num = temp1 + temp2;
else if (cur.op == '-') temp.num = temp1 - temp2;
else if (cur.op == '*') temp.num = temp1 * temp2;
else temp.num = temp1 / temp2;
s.push(temp);
}
}
return s.top().num;
}
int main() {
mp['+'] = mp['-'] = 1;
mp['*'] = mp['/'] = 2;
while (getline(cin, str), str != "0") {
for (string::iterator it = str.begin();it != str.end();++it) {
if (*it == ' ') str.erase(it);
}
while (!s.empty()) s.pop();//这里不写的话会导致后续结果出错
change();
// while(!q.empty()){//中间段的测试代码
// if(q.front().flag==1) printf("%f",q.front().num);
// else printf("%c",q.front().op);
// q.pop();
// }
printf("%.2f\n", calculate());
}
return 0;
}
Problem E
#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;
int main(){
int n;
scanf("%d",&n);
getchar();
while(n--){
string str;
getline(cin,str);
stack<char> st;
bool flag;
for(int i=0;i<str.length();++i){
flag=true;
if(str[i]=='('||str[i]=='['||str[i]=='{') st.push(str[i]);
else if(str[i]==')'){
if(!st.empty()&&st.top()=='(') st.pop();
else{
flag=false;
break;
}
}else if(str[i]==']'){
if(!st.empty()&&st.top()=='[') st.pop();
else{
flag=false;
break;
}
}else if(str[i]=='}'){
if(!st.empty()&&st.top()=='{') st.pop();
else{
flag=false;
break;
}
}
}
if(st.empty()&&flag) printf("yes\n");
else printf("no\n");
}
return 0;
}
《算法笔记》6.8小节——C++标准模板库(STL)介绍->pair的常见用法详解
重心在哪里
#include<cstdio>
#include<utility>
using namespace std;
int main() {
int n;
while (scanf("%d", &n), n) {
while (n--) {
double a1, b1, a2, b2, a3, b3;
scanf("%lf %lf %lf %lf %lf %lf", &a1, &b1, &a2, &b2, &a3, &b3);
pair<double, double>a(a1, b1), b(a2, b2), c(a3, b3), res;
res = make_pair((a.first + b.first + c.first) / 3.0, (a.second + b.second + c.second) / 3.0);
printf("%.1f %.1f\n", res.first, res.second);
}
}
return 0;
}
《算法笔记》6.9小节——C++标准模板库(STL)介绍->algorithm头文件下常用函数介绍
求最大最小数
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
int n;
while (scanf("%d", &n) != EOF) {
vector<int> vi;
for (int i = 0;i < n;++i) {
int num;
scanf("%d", &num);
vi.push_back(num);
}
vector<int>::iterator it = vi.begin();
sort(it, it + n);
printf("%d %d\n", vi[n - 1], vi[0]);
}
return 0;
}
全排列
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main() {
char str[10];
while (scanf("%s", str) != EOF) {
int len = strlen(str);
do {
printf("%s\n", str);
} while (next_permutation(str, str + len));
printf("\n");
}
return 0;
}
数组逆置
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main() {
string str;
while (getline(cin, str)) {
reverse(str.begin(), str.end());
cout << str << endl;
}
return 0;
}