统计子矩阵个数
满足单调性,用双指针优化。
最大矩形
满足单调性,且满足可合并性。故可进一步用单调栈优化,但当它求个数时,亦要 O ( n 3 ) O(n^3) O(n3)
扰乱字符串
一道很有意义的区间DP,一般而言,一维区间dp是在一个数组上做的,时间复杂度为 O ( n 3 ) O(n^3) O(n3),而这个二维dp是在两个数组上做的,时间复杂度为 O ( n 4 ) O(n^4) O(n4)。
1690. 石子游戏 VII
先手必胜需要证明。
1039. 多边形三角剖分的最低得分
线性dp可以有多维,以三维为例显著特点 f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]只会与 i , j , k i,j,k i,j,k规模减1的问题有关,这里每个变量可有两个选择,组合起来最多有六个。
二维线性dp
剑指 Offer II 097. 子序列的数目
字符串子串个数dp
典型特征, f [ i ] [ c h ] = s u m ( f [ i − 1 ] [ a − z ] ) f[i][ch]=sum(f[i-1][a-z]) f[i][ch]=sum(f[i−1][a−z]),因而可以进行优化,将复杂度从 26 n 26n 26n降到 26 + n 26+n 26+n
940. 不同的子序列 II
1235. 规划兼职工作
对字母串可执行的最大删除数
对于这一类问题,思考的时候从前往后,dp的时候从后往前。 n 2 n^2 n2时间预处理出lcp,可
用后缀数组优化但没必要, f [ i ] f[i] f[i]表示 s [ i : n − 1 ] s[i:n-1] s[i:n−1]所需的最大步数。
174. 地下城游戏
该问题如果正向思考,反向思考则能打开思路。
1406. 石子游戏 III
f [ i ] = m a x ( f [ i ] , s u m − f [ j ] ) ; f [ i ] 表示从 s t o n e s [ i : n ] 的石头先手最优能拿的数量 f[i]=max(f[i],sum-f[j]);f[i]表示从stones[i:n]的石头先手最优能拿的数量 f[i]=max(f[i],sum−f[j]);f[i]表示从stones[i:n]的石头先手最优能拿的数量
1140. 石子游戏 II
注意:题目中的M是变大后不会再变小的 f [ i ] [ j ] f[i][j] f[i][j]表示从i到结尾, M = j M=j M=j的最优解。
面试题 17.06. 2出现的次数
通用模板
class Solution {
public:
int calc(int n,int x){
int L,M,R=0;
int res=0;
long long P=1;
while(n){
L = n/10;
M = n%10;
if(x==0){
if(x==M){
if(L)res+=(L-1)*P+R+1;
}else res+=L*P;
}else{
if(x>M)res+=L*P;
else if(x==M)res+=L*P+R+1;
else res+=(L+1)*P;
}
n/=10;
R=R+M*P;
P*=10;
}
return res;
}
int numberOf2sInRange(int n) {
return calc(n,2);
}
};
902. 最大为 N 的数字组合
注意将不足N位的单独计算,方便枚举
1563. 石子游戏 V
f[i][j] 的最优解为可为其它子问题表示的最优解
1563. 石子游戏 V
1064. 小国王
预处理出合法状态和合法转移状态。
f [ i ] [ j ] = k f[i][j]=k f[i][j]=k,差值为 j j j,两个板中较短一个的最大长度为 k k k。
956. 最高的广告牌
寻找旋转排序数组中的最小值 II
链内单调递增,链外单调递减。
229. 多数元素 II
11. 盛最多水的容器
证明:
双指针,优先移动短的那边。 令 l 为左边界, r 为右边界,则 l m a x > = l , r m a x < = r 。 { c a s e 1 : l = l m a x , r = r m a x 已经找到最大值 c a s e 2 : l < l m a x , r = r m a x 此时移动 l , h [ l ] < h [ r ] c a s e 3 : l = l m a x , r < r m a x 此时移动 r , h [ r ] < h [ l ] c a s e 4 : l > l m a x , r > r m a x 此时既可移动 l , 也可移动 r ,但我们选择高度较低的一个 双指针,优先移动短的那边。\\ 令l为左边界,r为右边界,则lmax>=l,rmax<=r。\\ \begin{cases} case1:l=lmax,r=rmax& 已经找到最大值\\ case2:l
选择高度较低的偏移一定能得到正确结果。
45. 跳跃游戏 II
证明:
令 l = 0 , r = 0 。 则可计算从 l − r 的点可以辐射到的新的范围,其中 l = r + 1 , r = 最远距离。每一轮均选择可以辐射最远的点 . 假设最优解没有选择可以辐射最远的点,那么选择辐射最远的点不会使结果变差。 令l=0,r=0。\\ 则可计算从l-r的点可以辐射到的新的范围,其中l=r+1,r=最远距离。 每一轮均选择可以辐射最远的点.\\ 假设最优解没有选择可以辐射最远的点,那么选择辐射最远的点不会使结果变差。 令l=0,r=0。则可计算从l−r的点可以辐射到的新的范围,其中l=r+1,r=最远距离。每一轮均选择可以辐射最远的点.假设最优解没有选择可以辐射最远的点,那么选择辐射最远的点不会使结果变差。
179. 最大数
证明:
将数字转化为字符串,按如下规则 s t r a + s t r b > s t r b + s t r a 。 假设最优解中存在一个 s t r a + s t r b > s t r b + s t r a ,且 s t r a 在后, s t r b 在前,则能找 到一个更优解是将这两个子串交换。故最优解中不存在违反上述规则的情况。 将数字转化为字符串,按如下规则 stra+strb>strb+stra。\\ 假设最优解中存在一个stra+strb>strb+stra,且stra在后,strb在前,则能找\\到一个更优解是将这两个子串交换。故最优解中不存在违反上述规则的情况。 将数字转化为字符串,按如下规则stra+strb>strb+stra。假设最优解中存在一个stra+strb>strb+stra,且stra在后,strb在前,则能找到一个更优解是将这两个子串交换。故最优解中不存在违反上述规则的情况。
397. 整数替换
对于 x x x x x 01 结尾的,假设前面无 1 ,则为结果,否则,选择减 1 优于加 1 。 对于 x x x x x 11 结尾的,假设前面无 1 ,则差两步,前面有 1 ,选择加 1 优于选择减 1 。 对于xxxxx01结尾的,假设前面无1,则为结果,否则,选择减1优于加1。\\ 对于xxxxx11结尾的,假设前面无1,则差两步,前面有1,选择加1优于选择减1。\\ 对于xxxxx01结尾的,假设前面无1,则为结果,否则,选择减1优于加1。对于xxxxx11结尾的,假设前面无1,则差两步,前面有1,选择加1优于选择减1。
502. IPO
首先用需要资本排序。 可用资本是递增的,用堆维护当前所有可用资本,优先完成利润最大的。 首先用需要资本排序。\\ 可用资本是递增的,用堆维护当前所有可用资本,优先完成利润最大的。\\ 首先用需要资本排序。可用资本是递增的,用堆维护当前所有可用资本,优先完成利润最大的。
517. 超级洗衣机
1. 选定一个洗衣机,它要移动的次数为左右两边需要它移动的次数。 1.选定一个洗衣机,它要移动的次数为左右两边需要它移动的次数。 1.选定一个洗衣机,它要移动的次数为左右两边需要它移动的次数。
1686. 石子游戏 VI
贪心策略,和从大到小排序。 反证明,假设最优解不是按如上顺序拿的,则必然存在一个更优解。 情况一:取数顺序虽不是如上,但最终取的系列与贪心策略相同,该情况无须讨论 情况二:取数顺序不同,存在一个 a [ i ] + b [ i ] < a [ j ] + b [ j ] , 其中 i < j 且 i 被 a l i c e 取, j 被 b o b 取,则交换两项有: s u m A l i c e = s u m A l i c e − ( a [ i ] − a [ j ] ) , s u m B o b = s u m b o b − ( b [ j ] − b [ i ] ) ; 这种情况下, A l i c e 和 B o b 之间的分差会被拉大。显然是一个更好的解。 贪心策略,和从大到小排序。\\ 反证明,假设最优解不是按如上顺序拿的,则必然存在一个更优解。\\ 情况一:取数顺序虽不是如上,但最终取的系列与贪心策略相同,该情况无须讨论\\ 情况二:取数顺序不同,存在一个a[i]+b[i]贪心策略,和从大到小排序。反证明,假设最优解不是按如上顺序拿的,则必然存在一个更优解。情况一:取数顺序虽不是如上,但最终取的系列与贪心策略相同,该情况无须讨论情况二:取数顺序不同,存在一个a[i]+b[i]<a[j]+b[j],其中i<j且i被alice取,j被bob取,则交换两项有:sumAlice=sumAlice−(a[i]−a[j]),sumBob=sumbob−(b[j]−b[i]);这种情况下,Alice和Bob之间的分差会被拉大。显然是一个更好的解。
后缀数组
1044. 最长重复子串
877. 石子游戏
∣ A ∣ B ∣ A ∣ B ∣ A ∣ B ∣ 要求长度为偶数,先手可保证拿 A 序列还是 B 序列,而这其中必有一个大于另外一个 |A|B|A|B|A|B|\\ 要求长度为偶数,先手可保证拿A序列还是B序列,而这其中必有一个大于另外一个 ∣A∣B∣A∣B∣A∣B∣要求长度为偶数,先手可保证拿A序列还是B序列,而这其中必有一个大于另外一个
2029. 石子游戏 IX
首先这是无平局的游戏,那么只要先手无法找到必胜策略,则其必败。分类讨论。
6222. 美丽整数的最小增量
会就是会,不会就是不会,一定是产生进位的时候才会减小。
双指针分为两种,一种是从两端向中间集中,一种是从左往右。
向中间集中,一定要满足结果只在 [ l , r − 1 ] 或 [ l + 1 , r ] [l,r-1]或[l+1,r] [l,r−1]或[l+1,r]中。
11. 盛最多水的容器
本题思想是贪心,满足第一类双指针。
16. 最接近的三数之和
从左往右要满足, r ′ > r , 则 l ′ > = l r'>r,则l'>=l r′>r,则l′>=l。即当r单调时,l也单调。
2444. 统计定界子数组的数目
该题在局部上满足第二类双指针。
LCP 71. 集水器
在左下右围上一圈0,将每个正方形分成四块,给每个小三角形一个编号,从下往上,如果不能将小三角形与0连通,则这一点可以有水
在上下右右围上一圈0,如果小三角形能到达0,则表示小三角形不封闭,可以有水进来
剑指 Offer II 111. 计算除法
带权并查集
779. 第K个语法符号
934. 最短的桥
934. 最短的桥
2242. 节点序列的最大得分
这是一道很经典的题目,直接枚举复杂度很高,选择从中间那条边枚举另外两个端点,但这样复杂度依然会很高,可以只取左右最大的两个点即可。
一个节点被删去后的高度 = 兄弟节点对应的高度,祖先节点被删的高度的最大值 一个节点被删去后的高度=兄弟节点对应的高度,祖先节点被删的高度的最大值 一个节点被删去后的高度=兄弟节点对应的高度,祖先节点被删的高度的最大值
6223. 移除子树后的二叉树高度
以从左往右为例
本题的做法是单调栈+动态规划
907. 子数组的最小值之和
895. 最大频率栈
数组中出现次数超过一半的数字
class Solution {
public:
int moreThanHalfNum_Solution(vector<int>& nums) {
int n=nums.size();
int t=nums[0];
int cnt=1;
for (int i = 1; i < n; i ++ ){
if(nums[i]==t)cnt++;
else{
cnt--;
if(cnt==0){
t=nums[i];
cnt=1;
}
}
}
return t;
}
};
229. 多数元素 II
class Solution {
public:
vector<int> majorityElement(vector<int>& nums) {
vector<int> ans;
int r1,r2,c1=0,c2=0;
for(auto i:nums){
if(c1&&r1==i)c1++;
else if(c2&&r2==i)c2++;
else if(!c1)r1=i,c1=1;
else if(!c2)r2=i,c2=1;
else c1--,c2--;
}
c1=0,c2=0;
for(auto i:nums){
if(i==r1)c1++;
else if(i==r2)c2++;
}
if(c1>nums.size()/3)ans.push_back(r1);
if(c2>nums.size()/3)ans.push_back(r2);
return ans;
}
};
BFS+set
注意,C++ 的set类型自带lower_bound,不要用std::lower_bound库函数。
6365. 最少翻转操作数