一、绪论
要点杂记:
- 关键能力:将实际问题抽象成数学问题(路-->图/树);运用计算机知识(数据结构与算法)设计解决方案
- 三个层次:能默写算法-->能将句子想法转换为程序代码-->高效,健壮
- Runtime Error(运行错误)的可能原因:数组越界;除以0;调用了禁用的函数;递归过深/栈溢出
- Output Limit Exceeded 可能原因:忘关调试的输出;输出的死循环等
- 复杂度估计:
- 时间:不能超过一千万。例如,O(n^2)算法,则数据规模要<=3000,若大于,则可能要改用O(nlogn)算法。
- 空间:10^7的(long)int型数组,占用38MB(int 32b占4B)。log2 1e6≈20
- 2^31:2.1e10,2^63:0.9e19
- 别用<bits/stdc++.h>,可能有的平台不支持(导致编译错误),所以把那些头文件要记住,如:algorithm、string.h(memset用)等等
二、经典入门
IO:
- scanf函数有返回值:成功赋值的变量个数,EOF是-1。所有scanf("%d",&n)!=EOF就可以解决没有终止标志的输入问题
- scanf("%c", &ch); 可以读入换行和空格,若想用scanf,就要在%c前加上前面的\n或者空格!
- 对于不知道长度的数组输入,可以用这个方法因为cin后的空格或换行还在,实验表明中间都是一个空格ascii是32,最后会变成10(也就是换行)
- 格式符long long:%lld double:%lf,尽量都用double,别用float了
- printf格式
- %md:m位右对齐,不足位补空格
- %0md:不足m位则补0
- %.md:保留m位小数,这个是四舍五入的;想要去尾,则printf("%.2lf", n>0?n-0.05:n+0.05) 巧妙哦
数学基础知识点
- 判断闰年:能被400整除,或者能被4整除,不能被100整除
- x % 100 != 0 && x % 4 == 0 || x % 400 == 0
math.h/cmath(后者兼容前者?)
- fabs(x),对double x取绝对值,abs()有iostream就能用
- floor(x), ceil(x),对double x 向下和向上取整。floor(-1.2)=-2
- round(x),四舍五入取整,但是返回的还是double型变量,直接cout是整数
- pow(2.0, 3.0)=8.0,其实pow函数本身要求的double型的,不过这里直接cout的话,结果是8,可以用printf控格式
- sqrt(4.0)=2.0
- log(e)=1,如果要以2为底的log,需要用换底公式:log2 8=loge 8/loge 2,程序就是log(8)/log(2)=3
- sin(x),cos(x),tan(x);asin(x),acos(x),atan(x) 反三角 。如sin(3.141592653) ≈ 0,asin(1) ≈ 1.5708
指针与引用
- 正常都是用指针吧?就不用引用了。。?https://blog.csdn.net/qq_41603898/article/details/82995327
- 《算法笔记》里二叉树那里,因为要传入的数据类型就是指针,而如果要inplace操作就还要加上&
数组
- memset,只能用于0或-1,不然1:16843009,2:33686018
- 其他数字的初始化要用
- algorithm头文件的:fill(vec.begin(), vec.end(), value)
- 二维数组的话:fill(mapp[0], mapp[0]+N*N, value)。注意sizeof是:元素个数*单位元素所占字节数,而这里只要元素个数就行
- 二维/三维数组这种的理解:就当做几个维度的坐标在走,不要想着嵌套!
STL
- map
- 判空mp.count(x)==0;或者直接 if(!mp[x]) 也表示x不再mp里
- find获取迭代器(地址):it=mp.find(x)
- 遍历的话,用it,begin --》!=end,然后it->first,it->second
- 删除一个key直接mp.erase(key)或者能获取到it了直接mp.erase(it)
- #include<unordered_map> 提高效率
- string:
- insert(pos, str):在pos位置插入str
- erase(first, last):删除[first, last),这里是迭代器;也可以直接删除erase(it)单个元素;或者erase(pos,len)
- find(str)!=string::pos表示找到str,find函数返回str的首位置
- str.replace(pos,len,str2) 或者str.replace(it1,it2,str2)
- s.substr(index, len)返回子串
- set等 不能像string vector直接index取元素,要用迭代器 set<int>::iterator it; 或c++11新增的auto it=x.begin()很好用
- 且不能it直接+-,要用it++或it--来更新,倒序输出的话,直接在判断的里面用*--it!=se.begin()即可
- insert;erase;都是对一个元素的操作(set自动去重嘛,erase也可以用it指定区间);clear;
- 判断元素存在,可以用s.count()==1或者s.find(x)!=s.end()
- queue
三、tips总结
- 遇到除法非一定要考虑:除以0的问题。其实不仅是除法,很多特判也需要考虑这点
- 能除的尽的情况下,先除再乘(eg LCM问题)防止溢出;还有大数取末的时候也要用那个定理先模在加/乘
- 避免zz错误,如无参函数调用忘记加括号,导致返回值都是1
- 优先级问题(常用的):! > 算术运算符 > 移位>关系运算符 > 按位与>&& > || > 赋值运算符>逗号(最低)
- leetcode里int *a=int[n]时可能n为0,这里的编译器可能会报错?总之可能会RE,但是我后来直接申请int a[100000]AC了
- 时分秒的时间形式往往转化为秒会好计算