PAT 练习总结
笔记
-
设置存储hash的数组可以尽量设大一点。
-
查找一串数字里是否存在某个数的问题一般用hash。
-
c++中map可随意访问、任意插入,index,vector不行。
-
ASCII码共有128个,其中比较常见的ASCII码:
- 10 = ’\n‘
- 48~57: 0 ~ 9
- 65 ~ 90: ’A‘ ~ ’Z‘
- 97 ~ 122: ‘a’ ~ ‘z’
-
C语言定义数组的方法:
int a[] = {1, 2, 3}; // 不定长数组,长度由元素个数决定。
int a[N];// 定长数组 。
int *a;// 定义指针
-
二维数组:
int a[10][10]
vector<int> a[10]
char a[10][10]
:字符串数组
-
C语言往函数传数组的方法:
int fuc(int *a, int size){int n = *(a + 0)}; // 传入指针和大小两个变量
int fuc(int a[], int size){}; // 传入数组和大小两个变量
int fuc(int a[10]){}; // 只传入数组一个变量
-
判断某数是否为素数:
bool isPrime(int n){ if(n == 0 || n == 1) return false; // 要考虑数字0和1 for(int i = 2; i <= sqrt(n); i++) // 是i <= sqrt(n),而不是 i <= n / 2。 if(n % i == 0) return false; return true; }
-
使用
sqrt()
需要#include <cmath>
-
正向平方探测法,
pos = (key + i * i)% Tsize (0 <= i < Tsize)
。 -
C++中
tolower()
函数是把字符串都转化为小写字母,touppre()
函数是把字符串都转化为大写字母。- 需要
#include<iostream>
或#include<cctype>
- 需要
-
isupper()
、isdigit()
等判断字符的函数在头文件cctype
里- 特别的,
stoi()
是c11特性,不需导入头文件
- 特别的,
-
isdigit()
不需要调用什么包; -
将字符串 string 转化为对应的 int 型、 double 型变量:
stoi
、stod
-
stoi()
:只能将string型变量变成int类型变量(字符、字符数组不行!) -
把int / float变成字符串:
to_string(int/float)
-
getline(cin, str)
,这个函数可读入一整行的字符串(包括空格) -
在字符串中查找字符可用
str.find(c)
,若没找到,会返回string::npos
。所以判断字符串中有无字符可用if(s.find(c) != string::npos)
。 -
查找字符串a是否包含子串b,不是用
strA.find(strB) > 0
而是strA.find(strB) != string:npos
; -
获取字符串的子串:
str.substr(index)
/str.substr(index, num)
- 可用
str.substr()
分割字符串;
- 可用
-
for循环内判断和赋值的灵活使用:
可以用for循环找到不符合条件的元素的下标j,如:
for(j = i; j < s.length() && s[j] == s[i]; j++); // 找到与当前数字s[i]不同的数字的下标 or 记录最后一个数字后一位下标
-
C语言的
scanf
、printf
语法:-
输入字符串:
#include <iostream> int main(){ char a[100]; scanf("%s", a); // input printf("%s", a); // output return 0; }
-
用字符串的方法(如
strlen()
)时要#include <string.h>
(#include <string>
没用) -
c语言字符串用
strlen()
要调用#include <string.h>
-
#include <iostream> int main(){ double a; scanf("%lf", &a); // 若输入2.3.4,赋值给a的值是2.3 return 0; }
-
double型变量:
scanf
格式符为%lf
printf
格式符为%f
-
输出格式:
- %md:使不足m位的的int型变量以m位进行右对齐输出,高位用空格补齐
- %0md:同上,不同处是用0补齐
- %.mf:使浮点数保留m位小数输出
-
-
C++的
sscanf
、sprintf
语法:-
两者均在
#include<cstdio>
头文件下 -
返回值:
-
sscanf()
:如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。即,若输入不规范,不会把不规范的东西赋值给变量。
-
sprintf()
:如果成功,则返回写入的字符总数,不包括字符串追加在字符串末尾的空字符。如果失败,则返回一个负数。 -
sscanf()
可以理解为:string+scanf;ssprintf()
可以理解为:string+printf;理解:
scanf("%d",&n);
和printf("%d",n);
可以理解为:(screen表示屏幕)scanf(screen,"%d",&n);
:把screen的内容以"%d"的格式传输到n中 (从左到右)printf(screen,"%d",n);
:把n以"%d"的格式传输到screen上 (从右到左)
sscanf()
和sprintf()
:sscanf(str, "%d", &n);
:把string的内容以"%d"的格式传输到n中 (从左到右)sprintf(str, "%d", n);
把n以"%d"的格式传输到string上 (从右到左)
-
sscanf()
和sprintf()
比较复杂的应用:-
sscanf()
:#include <cstdio> using namespace std; int main() { int n; double db; char str[] = "2018:3.14,hello"; char s[100]; sscanf(str, "%d:%lf,%s", &n, &db, s); printf("n=%d db=%.2f s=%s", n, db, s); return 0; }
输出:
n=2018 db=3.14 s=hello
-
sprintf()
:#include<cstdio> using namespace std; int main() { int n=12; double db=3.1415; char s[] = "good"; char str[100]; sprintf(str, "%d:%lf,%s", n, db, s); printf("%s\n",str); return 0; }
输出:
12:3.141500,good
-
-
-
-
只有C++有
getline(cin, str)
,C语言没有 -
cin >> n;
后如果要用getline(cin, str)
,需要先cin.ignore();
:因为输入n后会有一个
\n
,会导致getline()捕获这个\n
后中断,所以要加cin.ignore();
-
reverse(a.begin(), a.end)
:逆序(或反转),多用于字符串、数组、容器,只能转置线性容器-
需
#include <algorithm>
。 -
用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数无返回值。
-
和
sort()
一样,只能对线性容器进行排序(如vector
,list
,deque
)。map和set都是按键值对存的,所以不能用。
-
-
a为浮点数时,
to_string(a)
只会保留小数点后6位小数 -
结构体增加一个元素:
{it.first, it.second}
-
STL容器:
-
string
-
vector
-
初始化:
vector<int> v;
-
初始化时定义大小后会初始化为0,不定义大小就不会初始化为0;
vector<int> v(10); // 初始化vactor大小为10,其中每个元素都被初始化为0 vector<int> v // 大小和元素都没被初始化
-
若想输入vector的值,需要先初始化为0
-
-
在v的最后插入一个新元素:
v.push_back(i)
;
-
-
map
- 初始化:
map<string, int> m;
- 初始化后所有元素被初始化为0
- 因为map按键值排序了,所以不能按顺序输出m;unordered_map则是无序存储的,也不能按顺序输出m
- 初始化:
-
set
-
set会自动排序和去重
-
set,unordered_set:set是有序的(从小到大排序);unordered_set是无序的,数据的存放位置也是是无序的;
-
访问元素:用迭代器
-
查找特殊元素:
#include <iostream> #include <set> using namespace std; int main(){ set<int> s = {0, 3, 1, -2, 10}; auto pos = s.find(-2); // 先找这个元素的位置,返回一个迭代器 cout << *pos; // 取值,输出 return 0; }
-
-
遍历容器的方法
-
使用迭代器遍历:
v.begin()
是⼀个指针,指向容器的第⼀个元素,v.end()
指向容器的最后⼀个元素的后⼀个位置,所以迭代器指针it 的for循环判断条件是it != v.end()
。vector<int> v = {1, 2, 3}; for(auto it = v.begin(); it != v.end(); it++) // auto相当于 vector<int>::iterator 的简写 cout << *it << endl; // 访问vector的元素用*it map<int, int> m; m[1] = 100; m[2] = 200; for(auto it = m.begin(); it != m.end(); it++) cout << it -> first << " " << it -> second << endl; // 访问map的键用it -> first,访问map的值用it -> second
auto
是C++11⾥⾯的新特性,可以让编译器根据初始值类型直接推断变量的类型
-
基于范围(range-based)的for循环:遍历数组中的每个元素
int a[3] = {1, 2, 3}; for(int i : a) cout << i << endl; vector<int> v = {1, 2, 3}; for(auto it : v) cout << it << endl;
-
-
-
sort()、自定义cmp
- 需
#include <algorithm>
- 注意传入cmp的变量都是地址;
- 升序:
a > b
;降序:a < b
。 sort
算法只能对线性容器进行排序(如vector
,list
,deque
),map
是一个集合容器,它里面存储的元素是pair,不是线性存储的(像红黑树),所以利用sort不能直接和map结合进行排序;
- 需
-
若运行超时,可能是用了
cout
,改成printf()
一般就能解决问题。 -
避免超时的方法:
- 用空间换时间:
1.hash
2. 能用map
直接找到对应的值,就别用for
循环一个一个找 - 不用
cin、cout
,用scanf()、printf()
; - 在循环里,可用提前用
break;
或return 0
退出; - 在
for
循环外面定义i
; - 如果使用
map
或set
超时了,不考虑排序的情况,可以用unordered_map
和unordered_set
- 用空间换时间:
-
结构体:定义结构体数组时,vector<>里是结构体名称,不是变量名;
struct good_pair{ string good1; string good2; }; vector<good_pair> list(n);
-
初始化数组元素的方法:
-
定义成全局变量,即将
int a[N]
放在main外,这样a所有元素都会被初始化为0; -
int a[10] = {0};
-
vector
的初始化:vector<int> a(10);
-
-
vector<item> query(n);
结构体也会被初始化为0; -
map[key]
查询无果,就会返回0。 -
重载和引用(详细笔记看这):
-
重载(来自菜鸟教程):名字相同,参数和定义不同。
-
引用:和原变量本质上是一个东西,只不过是原变量的一个别名。
-
-
在vector里查找是否有某元素:若
query.find(q) == query.end()
为true
,说明没找到;为false
,说明找到了。 -
要排序的东西可以放到数组里。
-
在排序有很多要求时,结构体真的很好用!
-
以后多用三目运算符,可以减少代码量。
-
如果一个东西有多个属性,就用结构体;
-
结构体的元素可以用
{}
表示;struct stu{ string name; int age; int sex; }; int main(){ stu student1 = {"Lily", 10, 1}; stu student2 = stu{"Tom", 11, 0}; // 也可在打括号前写结构体名字 return 0; }
-
四舍五入:
round()
- 需
#include <cmath>
round(x)
返回x的四舍五入整数值。ceil(x)
返回不小于x的最小整数值(然后转换为double型)。floor(x)
返回不大于x的最大整数值。
- 需
-
若思路很乱,可尽可能用多的容器/遍历去存多个信息。比如有一题里学校的信息就可以用三个容器:
-
vector<applicant> sch[101];
:存学校里面的学生信息 -
int quota[101] = {0};
:存学校的招生指标 -
int cnt[101] = {0};
:存学校当前录取的学生数这样思路清晰、操作方便;
-
-
可以将完成某项工作的代码封装成函数,如“判断素数”、“数字转换”和“计算和”之类的;
-
用太多stl容器容易超时;
-
如何获得一个整数的各位数:
int num; scanf("%d", &num); while(num != 0){ printf("%d ", num % 10); num /= 10; }
-
用
v.resize(k)
给v重新定义大小后,可以直接输入。stu[i].choices.resize(k); for(j = 0; j < k; j++) scanf("%d", &stu[i].choices[j]); }
易错
-
string
类型的变量只能用cin
输入,不能用scanf()
输入!!!输出可用
cout
和printf()
,但是要先把变量.c_str()
:printf("%s", str.c_str())
。- 为了与C兼容,在C中没有string类型,故用
printf()
输出string时,必须通过string类对象的成员函数c_str()
把string对象转换成C中的字符串样式
- 为了与C兼容,在C中没有string类型,故用
-
查找字符串a是否包含子串b,而是
strA.find(strB) != string:npos
;判断字符串中有无字符可用if(s.find(c) != string::npos)
。 -
有关数字的问题,要注意
num == 0
的情况; -
我做题经常有一两个测试点每通过,是因为一般情况下我只考虑所给样例里的情况,没有严谨的所有情况。我做题都是凭直觉,一点都不严谨!!!要注意细节。
-
for有循环内多个判断条件:注意
i++
或者i--
! -
输出时要注意英文的单复数形式!!!
- n = 1时输出:“There is 1 account.”
- n > 1时输出:“There are 3 accounts.”
-
if()
里有多个判断条件记得要打括号! -
数组不能设得太大了,不然会报栈错误
-
如果数字太大,是不能用普通的hash去存的,因为没有那么大的数组,用map存就能解决问题。
-
将
i
定义在for循环
外后,再用的时候忘记初始化了,所以一直报栈溢出的错; -
while()
里的判断条件应该和if()
一样的,符合条件才执行循环语句里的东西; -
注意
while()
允许运行的条件是满足条件的时候,还要注意i == 0
的情况! -
别把要输入的变量定义成测试样例里的值!
-
若删除set元素后还需迭代set,记得要更新迭代器的位置,因为set已经变了,如:
while(it != singles.end()){ if(singles.find(couples[*it]) != singles.end()){ // 有一对情侣就将他们删除 singles.erase(*(singles.find(couples[*it]))); // 先删除这个人的情侣,再删除这个人 singles.erase(*it); it = singles.begin(); // 因为删除后set变了,该从头遍历set }
-
用
while(one[j] != one_part) j++;
去找元素可能会出现数组越界,会报段错误,改成用for
去找,就能解决段错误了。 -
在访问数组元素时,经常用错下标,比如:
for(i = 0; i < 10; i++){ for(j = 0; j < 5; j++){ if(s[j] == '0') // 我经常会粗心写成s[i] printf("%c\n", s[j]); } }
-
有时候偷懒,想复制之前写好的部分,会忘记改了,比如:
if(m < 12 && ten[m] == one_part){ // 从下面复制ten[m] == ten_part忘记改成ten[m] == one_part
-
(int / int) 为int类型,若想获得float类型,应先将int变量强制转换成float类型;
-
若我想生成二维vector,在往二维vector里插入新vector时,要注意新vector的类型要和二维vector定义的一致;
题目分类
类型 | 题目 | 刷题笔记 |
---|---|---|
hash | 1154 | |
hash | 1145 | |
hash | 1134 | |
hash | 1092 To Buy or Not to Buy (20 分) | https://blog.csdn.net/SSibyl/article/details/115559781?spm=1001.2014.3001.5501 |
hash | 1084 Broken Keyboard (20 分) | https://blog.csdn.net/SSibyl/article/details/115920266?spm=1001.2014.3001.5501 |
hash | 1078 Hashing (25 分) | https://blog.csdn.net/SSibyl/article/details/116198964?spm=1001.2014.3001.5501 |
hash | 1050 String Subtraction (20 分) | https://blog.csdn.net/SSibyl/article/details/116199564?spm=1001.2014.3001.5501 |
hash | 1048 Find Coins (25 分) | https://blog.csdn.net/SSibyl/article/details/116210005?spm=1001.2014.3001.5501 |
hash | 1041 Be Unique (20 分) | https://blog.csdn.net/SSibyl/article/details/116210571?spm=1001.2014.3001.5501 |
字符串 | 1152 Google Recruitment (20 分) | https://blog.csdn.net/SSibyl/article/details/116242675?spm=1001.2014.3001.5501 |
字符串 | 1140 Look-and-say Sequence (20 分) | https://blog.csdn.net/SSibyl/article/details/116243889?spm=1001.2014.3001.5501 |
字符串 | 1108 Finding Average (20 分) | https://blog.csdn.net/SSibyl/article/details/116352827?spm=1001.2014.3001.5501 |
字符串 | 1082 Read Number in Chinese (25 分) | https://blog.csdn.net/SSibyl/article/details/116357128?spm=1001.2014.3001.5501 |
字符串 | 1077 Kuchiguse (20 分) | https://blog.csdn.net/SSibyl/article/details/116358127?spm=1001.2014.3001.5501 |
字符串 | 1073 Scientific Notation (20 分) | https://blog.csdn.net/SSibyl/article/details/116428996?spm=1001.2014.3001.5501 |
字符串 | 1061 Dating (20 分) | https://blog.csdn.net/SSibyl/article/details/116536169?spm=1001.2014.3001.5501 |
字符串 | 1035 Password (20 分) | https://blog.csdn.net/SSibyl/article/details/116463362?spm=1001.2014.3001.5501 |
字符串 | 5. 1005 | |
字符串 | 6. 1001 | |
STL | 1153 Decode Registration Card of PAT (25分) | https://blog.csdn.net/SSibyl/article/details/116497987?spm=1001.2014.3001.5501 |
STL | 1149 Dangerous Goods Packaging (25 分) | https://blog.csdn.net/SSibyl/article/details/116543547?spm=1001.2014.3001.5501 |
STL | 1144 The Missing Number (20 分) | https://blog.csdn.net/SSibyl/article/details/116545641?spm=1001.2014.3001.5501 |
STL | 4. 1141 | |
STL | 1137. Final Grading (25) | https://blog.csdn.net/SSibyl/article/details/116712638?spm=1001.2014.3001.5501 |
STL | 1129 Recommendation System (25 分) | https://blog.csdn.net/SSibyl/article/details/116712459?spm=1001.2014.3001.5501 |
STL | 1124 Raffle for Weibo Followers (20 分) | https://blog.csdn.net/SSibyl/article/details/116716031?spm=1001.2014.3001.5501 |
STL | 1120 Friend Numbers (20 分) | https://blog.csdn.net/SSibyl/article/details/117200788?spm=1001.2014.3001.5501 |
STL | 1121 Damn Single (25 分) | https://blog.csdn.net/SSibyl/article/details/116719546?spm=1001.2014.3001.5501 |
STL | 1112 Stucked Keyboard (20 分) | https://blog.csdn.net/SSibyl/article/details/116800307?spm=1001.2014.3001.5501 |
STL | 1100 Mars Numbers (20 分) | https://blog.csdn.net/SSibyl/article/details/116806960?spm=1001.2014.3001.5501 |
STL | 1. 1095(没做) | |
STL | 1071 Speech Patterns (25 分) | https://blog.csdn.net/SSibyl/article/details/116895581?spm=1001.2014.3001.5501 |
STL | 1063 Set Similarity (25 分) | https://blog.csdn.net/SSibyl/article/details/116897670?spm=1001.2014.3001.5501 |
STL | 1054 The Dominant Color (20 分) | https://blog.csdn.net/SSibyl/article/details/116900037?spm=1001.2014.3001.5501 |
STL | 1047 Student List for Course (25 分) | https://blog.csdn.net/SSibyl/article/details/117092103?spm=1001.2014.3001.5501 |
STL | 1039 Course List for Student (25 分) | https://blog.csdn.net/SSibyl/article/details/117201164?spm=1001.2014.3001.5501 |
排序 | 1. 1153 | |
排序 | 2. 1141 | |
排序 | 3. 1137 | |
排序 | 1125 Chain the Ropes (25 分) | https://blog.csdn.net/SSibyl/article/details/117201592?spm=1001.2014.3001.5501 |
排序 | 1113 Integer Set Partition (25 分) | https://blog.csdn.net/SSibyl/article/details/117248636?spm=1001.2014.3001.5501 |
排序 | 1101 Quick Sort (25 分) | https://blog.csdn.net/SSibyl/article/details/117255502?spm=1001.2014.3001.5501 |
排序 | 1083 List Grades (25 分) | https://blog.csdn.net/SSibyl/article/details/117253941?spm=1001.2014.3001.5501 |
排序 | 1080 Graduate Admission (30 分) | https://blog.csdn.net/SSibyl/article/details/117373576?spm=1001.2014.3001.5501 |
排序 | 1062 Talent and Virtue (25 分) | https://blog.csdn.net/SSibyl/article/details/117464964?spm=1001.2014.3001.5501 |
模拟 | 1002 A+B for Polynomials (25 分) | https://blog.csdn.net/SSibyl/article/details/118694245?spm=1001.2014.3001.5501 |