week32
312 - 戳气球
经典的区间dp问题了,记住记住区间dp是先枚举长度 再枚举左端点
他这个状态设计注意一下 l 和 r 都是没有打掉的 因为计算分数需要 
还有一个优化: 每次计算nums[l] * nums[k] * nums[r] 可以先把nums[l] * nums[r] 存下来
class Solution {
public:
int maxCoins(vector<int>& nums) {
int n = nums.size();
nums.insert(nums.begin(), 1);
nums.push_back(1);
vector<vector<int>> f(n + 2, vector<int>(n + 2));
// 区间DP模板
for(int len = 3; len <= n + 2; len++)
for(int l = 0; len + l - 1 <= n + 1; l++)
{
int r = l + len - 1;
int reslr = nums[l] * nums[r];
for(int k = l + 1; k < r; k++)
f[l][r] = max(f[l][r], f[l][k] + f[k][r] + reslr * nums[k]);
}
return f[0][n + 1];
}
};313 - 超级丑数
复习一下丑数系列:
263 - 丑数
只包含质因子2, 3, 5 的话 就把质因子2,3, 5 除干净 看看余数是不是1就可以了
264 - 丑数II
丑数的定义是一样的 请找出第n个丑数
有点三路归并的意思, 用 i j k来表示丑数序列中因子2 3 5对应的指针 避免一个丑数同时有多个因子
每次更新 2 * ugs[i], 3 * ugs[j], 5 * ugs[k] 中最小的一个追加在序列内
然后判断更新的数是不是2 3 5 的因子 是的话 对应指针++
对于本题无非是丑数II这个题的扩展,把2 3 5的质数列表扩展即可
但是这里找最小值可以换成堆
o(nk)
o(nlogk)
315 - 计算右侧小于当前元素的数量
保序离散化 + 树状数组 经典了吧 拿离散后的元素当下标 这样可以区间查询到比x大/小的元素个数了
保序离散化
树状数组
代码如下:
316 - 去除重复字母
给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)
去掉重复字母还不算 还要字典序最小 -> 肯定是贪心删除
做法:
每次判断答案字符串的最后一个字母T[j] 大于 S[i] 且 T[j]可删除 -> 删除 直到不行 维持这样的偏序关系 最终得到字典序最优的解
使用栈来贪心的构造最终的字符串,栈的更新规则如下。
前提是当前字符没有在栈中出现。如果当前字符比栈顶字符的值小,且栈顶字符不是最后一次出现,则栈顶出栈。
重复 2 直到栈空或栈顶不满足出栈条件。此时,将当前字符压入栈中,且标记当前字符出现过。
最后将栈中元素从栈底到栈顶的顺序输出。
318 - 最大单词长度乘积
两次枚举肯定是跑不掉的,但是如何快速判断两个字符串是否有相同字母?
二进制枚举的思想
用一个二进制数来表示每个字母是否出现过,这样用与运算就可判断是否有相同字母同时出现。
319 - 灯泡开关
数论题真的不会 记一下推导吧~

所以最终返回sqrt(n)的下取整就好
Last updated