- 最短路问题需要记录路径时,可以另外开一个数组记录从哪个点走过来的。如果需要找出多条长度一样的最短路径,可以类似邻接链表的形式记录被更新的点,最后用dfs搜索。
- a * b % mod = a % mod * b % mod
- 乘法运算时要注意是否超上限
- long long类型最大到1018
- 环形问题可考虑将字符串或是数组复制一次并连接在末端
- double类型转换为int时可能出现精度问题,将原数加上1e-8即可
- 枚举的数比较大时,可以考虑二分算法
- 超过longlong时使用double进行比较
- 层序遍历用BFS,前、中、后序遍历用递归
- 已知中序遍历和前、后序遍历中的一种,可以唯一的确定一颗二叉树;但已知前序遍历和后序遍历不能确定
- BST(二叉搜索树)的中序遍历一定有序
- 完全二叉树可以用一维数组存储,通过序号访问左右子树
- 浮点数二分循环退出条件是小于一个很小的数
- 长度为n数组w,用
next_permutation(w, w + n)
变成下一个全排列 - 字符串转整型用stoi函数,整型转字符串to_string函数(c++11支持)
- 用
isdigit()
、isupper()
、islower()
、isalpha()
函数判断是否为数字、大写字母、小写字母、字母 - 如果要求序列中左边(右边)比当前值小(大)的第一个数,可以用单调栈解决
- 双指针循环时注意第二个指针要小于容器的大小
- 字符串函数
find_first_of(),find_first_not_of(),find_last_of(),find_last_not_of()
- 异或的性质:满足交换律和结合律、任意整数和自身做异或运算的结果都等于 0、任意整数和 0 做异或运算的结果都等于其自身
- 动态规划的状态转移大多数情况是枚举上一种可能的状态,但也可以枚举当前状态,并转移到下一种状态
n < 30
时,可以考虑dfs+剪枝或状态压缩DP等算法- Bellman-fold算法可以求有边数限制的最短路,存边,循环k次(k为边数限制),本质是DP
- 多次访问二维数组的元素时,先用变量存储,可以加快运行速度,通过下标取元素较慢
- 判断图中是否有环,可以用拓扑排序
- 动态规划或最短路需要记录个数时,再开一个数组记录即可
- 负数转换成无符号整数就是它的补码
- set迭代器遍历方法
for (set<int>::iterator i = s.begin(); i != s.end(); i ++ ) cout << *i << ' ';
其中s.being()
是第一个元素,s.end()
是最后一个元素的下一个 - vector初始化
vector<int> a = {1, 2, 3}
- 计算
+ - *
时可以用a + b * _
组成代数系统,即使用两个变量记录答案 ~
运算符是补码取反(包含符号位)- 键容易映射的时候用数组比哈希表效率更高,如记录各个数位上数字出现的次数
- 一次取出二进制的最后n位,可以和n个1进行与运算
- 字符串哈希,用前缀哈希法,将字符串看做P进制数对一个数mod取模,经验值P取131,mod取264,
h[i]
表示前i
个字符的哈希值,求[l, r]
字符串区间的哈希值公式为h[r] - h[l - 1] * p[r - l + 1]
,相当于进行数位对齐再相减,其中p[r - l + 1]
为预处理P
的r - l + 1
次方 - 运算符重载
bool operator< (const Node& t) const { return len < t.len; }
,用于sort是升序,用于优先队列是降序(即不改变原排序方式,sort默认升序,优先队列默认大根堆),t
相当于bool cmp(Node& a, Node& b) {return a < b; }
中的b
,原对象相当于a
- C++中预定义好的
π
\pi
π 为
M_PI
- KMP时间复杂度
O(m + n)
遍历待匹配字符串a
时,比较a[i]
、p[j]
可能的情况为:
1.当前字符匹配时,同时移动 i++
,j++
2.当前字符不匹配,且j=0
时,只移动 i++
,j=0
不动
3.当前字符不匹配,且j!=0
时,i
不变,j
回跳,最多跳j
次,j>0
时才回回挑,j
的大小由情况1确定,而情况1总共不可能出现超过n
次,所以总回跳不会超过n
次
最坏情况,i++
次数(情况1+情况2)+ j
回跳(情况3)= n + 最坏n = 2n
即O(n)
,求ne数组时类似,为O(m)
- 最短路问题求路径时,从终点枚举到起点
- 图论问题套路:涉及多个节点的最短路,枚举中间节点
- 位运算符号最好加括号,防止出现优先级问题
- stable_sort相同元素不会交换位置
- 合法括号满足的条件:1.左右括号的数量相等;2.任意前缀中,左括号数量不少于右括号的数量
- g++编译c++代码main.cpp
g++ main.cpp -c -o main.o
g++ main.o -o main
./main
- 贪心算法证明思路:任意一个最优解都可以转换为贪心解,同时结果不会变差,说明贪心解小于等于最优解。由于是最优解,小于等于贪心解,故贪心解就是最优解
- 使用
0x3f3f3f3f
作为无穷大的原因是:两个0x3f3f3f3f
的和(0x7e7e7e7e
)只比int类型的最大值(0x7fffffff
)小一点,这样在两个无穷相加时能够保证不会溢出 - 大小写转换:a的ASCII码是97,二进制是0110 0001,A的ASCII码是65,二进制是0100 0001相差32,故异或2的5次方,即^32可以进行大小写转换
- 结构体重载运算符后,不能定义小根堆(使用
greater<>
) - 快速排序while条件不加等于,在所有数相等时,如果加了等于会直接从一边移动到另一边,时间复杂度为n方,不加等于每次会从一半的位置继续递归