-
字符串的循环移位
三次翻转 -
字符串的包含
哈希表 -
字符串全排列
next_permutation算法 -
字符串的所有组合
dfs -
字符串转整数
stoi(), stol(), 注意边界 -
回文判断:判断字符串是否为回文串
双指针从两头往中间扫描 -
判断链表是否回文
(1)快慢指针找中点(2)翻转后半部分(3)遍历比较两段链表 -
判断栈是否回文
出栈后再入栈,与原字符串比较是否完全相同 -
最长回文子串
manacher算法:(1)预处理(2)id记录最远回文串中心,mx记录最远回文串位置
扩展KMP:比较原串的后缀与翻转串的前缀的最长公共前缀 -
最长重复出现子串
next[]数组的最大值 -
最长公共子串
动态规划:
扩展KMP: -
寻找最小的K个数
排序,最小堆,partition算法 -
寻找和为定值的两个数
对于已排序的数组,可以双指针两头扫描 -
寻找二叉树中和为定值的从根节点出发的所有路径
dfs+剪枝 -
寻找和为定值的四个数
枚举+二分 -
寻找和为定值的多个数
转化为01背包问题 -
最大连续子数组和
动态规划:maxSum记录最大和,curSum记录当前和,当curSum小于0时重置为当前元素值 -
最大子矩阵和
动态规划:枚举i行到j行范围,类比最大连续子数组和,求出行范围内从第0列到第k列的总和curSum,当curSum小于0时重置为当且列的和 -
跳台阶问题
斐波那契递推 -
换硬币问题:100元钱,有1元,2元,5元,10元面值的硬币,有多少种换法
完全背包问题 -
奇偶数排序:奇数放在前面,偶数放在后面,可改变相对顺序
双指针 -
荷兰国旗问题:数组只含0,1,2,要求0排最前,1排中间,2排最后
三指针,类比快排算法 -
唯一重复的元素
正负标记法 -
三个只出现一次的数:有三个数只出现一次,其余数均出现两次,找出这三个数
哈希 -
两个只出现一次的数:有两个数只出现一次(或奇数次),其余数均出现两次(或偶数次),找出这两个数
全部异或,根据异或的1比特位进行分类,再分别异或 -
n个整数中1出现的次数
动态规划保存结果 -
寻找接近给定和的若干个数
负数转正数,转化为背包问题 -
寻找和为定值的连续子数组
前缀和+哈希 -
寻找直方图中面积最大的矩形
类比接雨水,单调栈 -
串中取串:n个数,求出子串中数字和mod 3 = 0的串
尺取法 -
从一列数中删除尽可能少的数,使得数组变成山脉数组
动态规划,dp1[i]表示以i结尾的最长递增串长度,dp2[i]表示以i开头的最长递减串长度 -
波浪数组查找某个数
扩展二分 -
最长递减子序列
朴素dp:
队列优化: -
数字映射:下排的每个数都是上排的对应数字在下排出现的次数。
0:n-4次,1:2次,2:1次,n-4:1次 -
数组分割:数组长度为n,分割成m份,要求各份的和相等,求m的最大值。
二分查找 -
旋转数组的最小值
同构字符串的最小表示 -
鸡蛋放篮子:n个鸡蛋放到m个篮子,篮子不能为空,要满足对于任意不大于n的数量,能用若干个篮子的鸡蛋的总数表示。求所有满足条件的放法。
dfs,让篮子鸡蛋数递增,保证从小到大的所有数都能表示出来 -
数组分裂:n个元素的数组,分割成两组,使得两组的和的差绝对值最小
01背包问题 -
合并两个排序数组
双指针 -
数组的等和问题:n个元素,取m个,使得m个数的和等于另外n-m个数的和
背包问题 -
任务的分配:n个任务委派给n个人,每个人做的不同任务的花费为cost[i][j],求总花费最小的分配方式。
匈牙利算法、二部图的完美匹配。 -
站点之间的距离:已知相邻站点间的距离,高效地求任意站点间地距离
前缀和 -
数组的逆序对个数
归并排序衍生:
树状数组:先离散化,对于每个数,求出范围内前缀和,然后向树状数组添加这个数 -
格子涂色
动态规划 -
鸡蛋掉落问题
动态规划+记忆化搜索+二分:dp(K, N) = 1 + min(max(dp(K - 1, X - 1), dp(K, N - X)))
在X层蛋碎,则往下找;在X层蛋未碎,则往上找。 -
统计出现次数最多的数据
hash_map,map等 -
上亿行数据的快速查询
B树、B+树 -
二叉树节点的最近公共祖先(LCA)
dfs求路径:比较最后一个公共元素
线段树:预处理+查询 -
求二叉树节点的最大距离
两次dfs:
直接递归: -
求二叉树的深度
dfs -
树节点的和:给定二叉树,每个节点的值都是整数,找到一个子树使它的和最大。
后序遍历: -
O(1)空间遍历二叉树
Morris遍历法: -
行列递增矩阵的查找
分治法:在对角线二分查找,然后在左下和右上两个矩阵分别查找
定位法:从右上角开始,若比target大就往左,若比target小就往下 -
出现次数超过一半的数
动态规划:curAns和curCnt,与curAns相同则curCnt++;否则curCnt–;若curCnt减为0,则更行curAns。
55. 字符串模式匹配:KMP
void getNxt() {
memset(nxt, 0, sizeof(nxt));
nxt[0] = -1;
int j = 0, k = -1;
while (j < n) {
if (k == -1 || str[k] == str[j]) {
j++, k++;
nxt[j] = k;
} else k = nxt[k];
}
}
int kmp(void) {
int cnt = 0;
getNxt();
int i = 0, j = 0;
while (i < n) {
if (j == -1 || T[i] == W[j]) i++, j++;
else j = nxt[j];
if (j >= m) j = nxt[j], cnt++;
}
return cnt;
}
-
最大连续乘积子数组
动态规划:同时记录最大值mx和最小值mi,遇到负数则交换两者 -
字符串编辑距离(任意位置插入,替换,删除)
动态规划:dp[i][j]表示S[0i]到T[0j]的最短编辑距离,则
dp[i][j] = min { dp[i-1][j] + 1, S[i]不在T[0~j]中;
dp[i-1][j-1] + 1/0, S[i]在T[j]中,当S[i]==T[j]时取0;
dp[i][j-1] + 1, S[i]在T[0~j-1]中 } -
格子取数问题
动态规划:类比数塔问题 -
骨牌问题(1*2骨牌平铺)
边界dp -
Tire树
-
找到链表倒数第n个元素
先后指针 -
判断两个无环链表是否相交
是否相交:判断尾节点是否相同即可
找到第一个交点:根据长度,设先后指针 -
判断链表是否有环
是否有环:快慢指针
找到环的起点:在相遇点和起点再设两个同步指针,一定会在入口点相遇 -
全零矩阵:对矩阵某个元素加一时,其周围四个元素也会加一,能否得到指定整数矩阵
开关问题:枚举第一行状态,接下来每一行都与上一行有关 -
设计min栈:一个栈保存值,一个栈保存最小值
-
两个栈实现队列:一个栈负责入,一个栈负责出
-
八皇后问题:dfs
-
最小生成树:prim,kruskal
-
蚂蚁爬杆:弹性碰撞化为穿越
-
跑道赛马:5条跑道,每条跑道最多跑一匹马,25匹马最少比赛多少次可以比出最快的5匹马?
首先要至少比赛5+1次,得出杨氏矩阵,然后具体情况具体分析。