week29
282 - 给表达式添加运算符
给定一个仅包含数字 0-9 的字符串和一个目标值,在数字之间添加二元运算符(不是一元)+、- 或 * ,返回所有能够得到目标值的表达式。
这题显然就是DFS了 搜索每两个数字间可能出现的运算符并组合即可
问题就在于本题的方案如何记录, 这里用到了和线段树类似的运算表达式来简化 我们用一个形如
a + b * _的式子来表示所有方案 这样
+ 如果后面是 + : (a + b * c) + 1 * _
+ 如果后面是 - : (a + b * c) + -1 * _
+ 如果后面是 * : a + (b * c) * _这里我们额外规定最后一个数后面可以跟 +
using LL = long long;
class Solution {
public:
vector<string> ans;
string path;
LL target;
public:
vector<string> addOperators(string num, int target) {
path.resize(100);
this->target = target;
dfs(num, 0, 0, 0, 1); // 最开始 0 + 1 * _
return ans;
}
void dfs(string num, int u, int len, LL a, LL b)
{
if(u == num.size())
{
if(a == target) ans.push_back(path.substr(0, len - 1)); // 除去最后一个加号
}
else
{
LL c = 0;
for(int i = u; i < num.size(); i++)
{
c = c * 10 + num[i] - '0';
path[len++] = num[i];
// +
path[len] = '+';
dfs(num, i + 1, len + 1, a + b * c, 1);
if(i + 1 < num.size())
{
// -
path[len] = '-';
dfs(num, i + 1, len + 1, a + b * c, -1);
// *
path[len] = '*';
dfs(num, i + 1, len + 1, a, b * c);
}
// ! 注意这里前导0的情况
if(num[u] == '0') break;
}
}
}
};283 - 移动0
除了移动之外要保持非0元素的相对顺序 所以与其是移动0 实际上是移动所有非0元素
284 - 顶端迭代器
这题思路上是比较简单的 无非是增加一个缓存 和一个bool标记,调用peek 相当于提前调用了next, 再调用next的时候直接返回即可;
这里学习一下怎么调用父类同名函数 (指定namespace)
287 - 寻找重复数
这题经典套路了,看到1 ~ n 组成的数组就可以往数组元素作为下标想
这题就是把数组元素作为下标 连边 找到图中的环的起点,即为重复元素
图中环的起点怎么找呢? 快慢指针:1. 找到环 2. 让一个指针领先一个环的长度 3. 同时前进直到相遇 此时为起点
289 - 生命游戏
你可以使用原地算法解决本题吗? 请注意,面板上所有格子需要同时被更新: 你不能先更新某些格子,然后使用它们的更新后的值再更新其他格子。
很显然就是要额外定义状态
上一个状态 + 这一个状态 1 - 0 -> 2 1 - 1 -> 3
计算附近格子数的时候按照原来的状态 而不是更新过的状态
290 - 单词规律
还是比较基础的 之前应该是有一道一样的题(忘了是哪个了)
记录单词间的映射 注意这里不能只记录pattern 到 s 的映射 还要记录s中的单词是否曾经出现过(避免一个pattern对应多个单词)
最后通过判断i是否遍历到最后一个 来保证是一一对应的映射
Last updated