前言
4到5月期间连续打了好几周的周赛,就是为了多编程下,感觉做安全编程都少了,也是为了多编程编程。。。每次花费不了多长时间,下来补题也是,性价比也挺高,说不定硕士毕业就去开发了
周赛
leetcode第236场周赛
好长时间之后第一次打比赛,速度和思维都不行了,慢了很多,这不行,连最后一题的题目都没时间看,太难受了。。。
按照正常的话,第一题如果不想歪,一下看出出题人想要干什么,不想歪的前提是要看数据范围和时间复杂度,这样才能一下把一下不可行的思路去掉,每次敲代码都是有用的,第一题和第三题都想歪了。。。
5726. 数组元素积的符号
https://leetcode-cn.com/problems/sign-of-the-product-of-an-array/
上来我你嘛直接算了个乘积,都没看乘出来的大小,我笑了。。。
class Solution {
public:
int arraySign(vector<int>& nums) {
int fu = 0;
int zero = 0;
for(int i = 0;i < nums.size();++i){
if(nums[i] < 0){
fu++;
}else if(nums[i] == 0){
zero++;
}
}
if(zero > 0){
return 0;
}else if(fu % 2 == 0){
return 1;
}else{
return -1;
}
}
};
5727. 找出游戏的获胜者
https://leetcode-cn.com/problems/find-the-winner-of-the-circular-game/
忘了是约瑟夫环,也可以直接模拟,或者用递推,模拟感觉用python挺快的,毕竟删除啥的快
https://www.rainng.com/joseph-problem/
class Solution {
public:
int findTheWinner(int n, int k) {
int res = 0;
for (int i = 2; i <= n; i++) {
res = (res + k) % i;
}
return res + 1;
}
};
5728. 最少侧跳次数
https://leetcode-cn.com/problems/minimum-sideway-jumps/
刚开始啥都不想,直接上来暴力。。。暴力的前提是你想不到其他方法,但是这个复杂度基本一算,根本就不能暴力,暴个🐔儿
这个状态转移给的不能太明显了,特别注意的一个坑是,有些状态是不能转移过来的,比如前一个位置有障碍物,这样就转移不过来了,需要判断一下。
class Solution {
public:
const int inf = 0x3f3f3f3f;
int dp[500005][4];
int minSideJumps(vector<int>& obstacles) {
memset(dp, inf, sizeof(dp));
dp[0][2] = 0;
int len = obstacles.size();
for(int i = 1;i < len;++i){
if(obstacles[i] == 1){
if(obstacles[i - 1] != 2)
dp[i][2] = min(dp[i - 1][2], dp[i - 1][1] + 1);
if(obstacles[i - 1] != 3)
dp[i][3] = min(dp[i - 1][3], dp[i - 1][1] + 1);
}else if(obstacles[i] == 2){
if(obstacles[i - 1] != 1)
dp[i][1] = min(dp[i - 1][1], dp[i - 1][2] + 1);
if(obstacles[i - 1] != 3)
dp[i][3] = min(dp[i - 1][3], dp[i - 1][2] + 1);
}else if(obstacles[i] == 3){
if(obstacles[i - 1] != 1)
dp[i][1] = min(dp[i - 1][1], dp[i - 1][3] + 1);
if(obstacles[i - 1] != 2)
dp[i][2] = min(dp[i - 1][2], dp[i - 1][3] + 1);
}else{
dp[i][1] = dp[i - 1][1];
dp[i][2] = dp[i - 1][2];
dp[i][3] = dp[i - 1][3];
}
}
return min(min(dp[len - 1][1], dp[len - 1][2]), dp[len - 1][3]);
}
};
没算时间复杂度,傻子一样,敲了个bfs,还浪费了挺长时间调bug。。。
class Solution {
public:
queue<pair<pair<int,int>,int>>q;
int bfs(vector<int>& obstacles){
q.push(make_pair(make_pair(0,2),0));
int ans = 0;
while(!q.empty()){
pair<pair<int,int>,int> tmp = q.front();
q.pop();
int pos = tmp.first.first;
int paodao = tmp.first.second;
int depth = tmp.second;
int flag = 0;
for(int i = pos + 1;i < obstacles.size();++i){
if(obstacles[i] == paodao){
if(obstacles[i - 1] != paodao % 3 + 1)
q.push(make_pair(make_pair(i - 1, paodao % 3 + 1), depth + 1));
if(obstacles[i - 1] != (paodao + 1) % 3 + 1)
q.push(make_pair(make_pair(i - 1, (paodao + 1) % 3 + 1), depth + 1));
flag = 1;
break;
}
}
if(flag == 0){
ans = depth;
break;
}
}
return ans;
}
int minSideJumps(vector<int>& obstacles) {
return bfs(obstacles);
}
};
leetcode第 237 场周赛
前两题的速度还是慢,还有第四题好简单啊,我他娘应该先做第四题,再做第三题,第三题模拟的很恶心,有些情况老是考虑不完美,气死了。。。
优先队列的用法有点忘了,哎,变菜了。。。
5734. 判断句子是否为全字母句
class Solution {
public:
bool checkIfPangram(string sentence) {
bool flag = true;
map<char,int>mp;
for(int i = 0;i < sentence.size();++i){
mp[sentence[i]]++;
}
if(mp.size() ==26){
flag = true;
}else{
flag = false;
}
return flag;
}
};
5735. 雪糕的最大数量
class Solution {
public:
int maxIceCream(vector<int>& costs, int coins) {
sort(costs.begin(),costs.end());
int ans = 0;
if(costs[0] > coins){
return 0;
}
for(int i = 0;i < costs.size();++i){
ans += costs[i];
if(ans > coins){
return i;
}
}
return costs.size();
}
};5735. 雪糕的最大数量
5736. 单线程 CPU
class Solution {
public:
typedef struct Node{
int id;
int st;
int et;
bool operator<(const Node& a) const
{
if(et == a.et){
return id > a.id;
}
return et > a.et; //大顶堆
}
}Node;
Node node[100005];
static bool compare1(Node a, Node b){
if(a.st == b.st){
if(a.et == b.et){
return a.id < b.id;
}
return a.et < b.et;
}
return a.st < b.st;
}
// static bool compare2(Node a, Node b)
// {
// if(a.et == b.et){
// return a.id > b.id;
// }else{
// return a.et > b.et;
// }
// }
vector<int> getOrder(vector<vector<int>>& tasks) {
for(int i = 0;i < tasks.size();++i){
node[i].id = i;
node[i].st = tasks[i][0];
node[i].et = tasks[i][1];
}
sort(node, node+tasks.size(), compare1);
priority_queue<Node>ptr;
vector<int>ve;
int len = tasks.size();
int time = node[0].st + node[0].et;
ve.push_back(node[0].id);
for(int i = 1;i < len;++i){
if(node[i].st <= time){
ptr.push(node[i]);
}
if(ptr.empty()){
time = node[i].st + node[i].et;
ve.push_back(node[i].id);
}else if(i + 1 < len && node[i + 1].st > time){
Node tmp = ptr.top();
ptr.pop();
ve.push_back(tmp.id);
time = time + tmp.et;
while(time < node[i + 1].st){
if(ptr.empty()){
time = node[i].st + node[i].et;
ve.push_back(node[i].id);
}else{
Node tmp = ptr.top();
ptr.pop();
ve.push_back(tmp.id);
time = time + tmp.et;
}
}
}
}
while(!ptr.empty()){
ve.push_back(ptr.top().id);
ptr.pop();
}
return ve;
}
};
5737. 所有数对按位与结果的异或和
class Solution {
public:
typedef long long LL;
LL bit1[35];
LL bit2[35];
int getXORSum(vector<int>& arr1, vector<int>& arr2) {
memset(bit1, 0, sizeof(bit1));
memset(bit2, 0, sizeof(bit2));
int len1 = arr1.size();
int len2 = arr2.size();
for(int i = 0;i < len1;++i){
int x = arr1[i];
int j = 0;
while(x){
if((x & 1) == 1){
bit1[j]++;
}
j++;
x = x >> 1;
}
}
for(int i = 0;i < len2;++i){
int x = arr2[i];
int j = 0;
while(x){
if((x & 1) == 1){
bit2[j]++;
}
j++;
x = x >> 1;
}
}
LL ans = 0;
for(int i = 31;i >= 0;--i){
LL x = (bit1[i] * bit2[i] * 1LL) % 2LL;
ans = ans * 2LL + x;
}
return ans;
}
};
leetcode第 238场周赛
5738. K 进制表示下的各位数字总和
https://leetcode-cn.com/problems/sum-of-digits-in-base-k/
class Solution {
public:
int sumBase(int n, int k) {
int sum = 0;
while(n != 0){
sum += (n % k);
n /= k;
}
return sum;
}
};
5739. 最高频元素的频数
https://leetcode-cn.com/problems/frequency-of-the-most-frequent-element/
这道题刚开始一看,没有想法,直接看的第三题,做完第三题然后才做的这道题,需要稍微想想,其实想一想就是滑动窗口,我当时没想到是滑动窗口
继续优化的话,ans这个空间可以去掉
class Solution {
public:
typedef long long LL;
LL sum[100005];
LL dp[100005];
int maxFrequency(vector<int>& nums, int k) {
int len = nums.size();
sort(nums.begin(),nums.end());
memset(sum, 0, sizeof(sum));
memset(dp, 0, sizeof(dp));
// for(int i = 0;i < len;++i){
// cout << nums[i] << " ";
// }
// cout << endl;
for(int i = 1; i < len;++i){
sum[i] = sum[i - 1] + (nums[i] - nums[i - 1]);
}
// for(int i = 0;i < len;++i){
// cout << sum[i] << " ";
// }
// cout << endl;
LL res = 0;
for(int i = 1;i < len;++i){
LL j = dp[i - 1];
LL num = nums[i] - nums[i - 1];
while(res + (j + 1) * num > k){
res -= (sum[i - 1] - sum[i - 1 - j]);
j--;
}
res = res + (j + 1) * num;
dp[i] = j + 1;
}
// for(int i = 0;i < len;++i){
// cout << dp[i] << " ";
// }
// cout << endl;
LL MAX = -1;
for(int i = 0;i < len;++i){
MAX = max(MAX, dp[i]);
}
return MAX + 1;
}
};
5740. 所有元音按顺序排布的最长子字符串
https://leetcode-cn.com/problems/longest-substring-of-all-vowels-in-order/
这个听简单的,应该想几个特殊情况的,代码写的有点问题
class Solution {
public:
int dp[500005];
int longestBeautifulSubstring(string word) {
int len = word.size();
memset(dp, -0x3f3f3f3f, sizeof(dp));
if(word[0] == 'a'){
dp[0] = 1;
}
map<char,int>mp;
mp['a'] = 1;
mp['e'] = 2;
mp['i'] = 3;
mp['o'] = 4;
mp['u'] = 5;
for(int i = 1;i < len;++i){
if(word[i] == 'a'){
dp[i] = 1;
}
if(mp[word[i]] == mp[word[i - 1]]){
dp[i] = dp[i - 1] + 1;
}else if(mp[word[i]] - mp[word[i - 1]] == 1){
dp[i] = dp[i - 1] + 1;
}
}
int MAX = 0;
for(int i = 0;i < len;++i){
if(word[i] == 'u'){
MAX = max(MAX,dp[i]);
}
}
if(MAX < 5){
return 0;
}
return MAX;
}
};
5741. 最高建筑高度
https://leetcode-cn.com/problems/maximum-building-height/
做的时候已经想到了从前往后扫,从后往前扫了,就是个思维题吧,只想到了更新限高,但是最后答案那里,没想好,不知道靠左右两个高度取到的高度是不是最优解,不能证明,我就放弃了,没尝试,而且也到饭点了
class Solution {
public:
int maxBuilding(int n, vector<vector<int>>& r) {
vector<int>x = {1, 0};
vector<int>y = {n, n - 1};
r.push_back(x);
r.push_back(y);
sort(r.begin(), r.end());
int len = r.size();
for(int i = 1;i < len;++i){
r[i][1] = min(r[i][1], r[i - 1][1] + r[i][0] - r[i - 1][0]);
}
for(int i = len - 2;i >= 0;--i){
r[i][1] = min(r[i][1], r[i + 1][1] + r[i + 1][0] - r[i][0]);
}
int MAX = 0;
for(int i = 0;i < len - 1;++i){
int h = (r[i][1] + r[i + 1][1] + r[i + 1][0] - r[i][0]) / 2;
MAX = max(MAX, h);
}
return MAX;
}
};
leetcode第 239场周赛
5746. 到目标元素的最小距离
https://leetcode-cn.com/problems/minimum-distance-to-the-target-element/
读题花费的时间较长,下次需要加快
class Solution {
public:
int getMinDistance(vector& nums, int target, int start) {
int len = nums.size();
int MIN = 0x3f3f3f3f;
for(int i = 0;i < len;++i){
if(nums[i] == target){
MIN = min(MIN, abs(i - start));
}
}
return MIN;
}
};
5747. 将字符串拆分为递减的连续值
https://leetcode-cn.com/problems/splitting-a-string-into-descending-consecutive-values/
这个暴力写的不太美观,应该用递归写的,这样代码更漂亮点
class Solution(object):
def splitString(self, s):
"""
:type s: str
:rtype: bool
"""
llen = len(s)
for i in range(llen):
x = int(s[0:(i + 1)])
index = i + 1
while True:
flag = False
if x - 1 == 0 and index < llen and int(s[index:(llen + 1)]) == 0:
return True
for t in range(index, llen):
if int(s[index:(t + 1)]) == x - 1:
flag = True
index = t + 1
x = x - 1
break
if index >= llen and flag:
return True
if not flag:
break
return False
5749. 邻位交换的最小次数
https://leetcode-cn.com/problems/minimum-adjacent-swaps-to-reach-the-kth-smallest-number/
这个真的不难,首先我知道next_permutation,接着主要是第二个,求最小的相邻元素交换次数,我觉得这个暴力的方法可能不是最小的(对于一些重复出现的字符),所以说一直在犹豫,有没有好的方法,没想到这个还真是最小的。。。。
class Solution {
public:
int getMinSwaps(string num, int k) {
string target = num;
for(int i = 0;i < k;++i){
//这个居然是迭代网上交换的,不会交换出小的嘛?
//next_permutation()函数功能是输出所有比当前排列大的排列,顺序是从小到大。
//prev_permutation()函数功能是输出所有比当前排列小的排列,顺序是从大到小。
next_permutation(target.begin(), target.end());
}
int len = num.size();
int ans = 0;
for(int i = 0;i < len;++i){
if(num[i] != target[i]){
int j = i + 1;
while(num[j] != target[i]){
j++;
}
ans += (j - i);
for(;j > i;--j){
swap(num[j], num[j - 1]);
}
}
}
return ans;
}
};
5748. 包含每个查询的最小区间
https://leetcode-cn.com/problems/minimum-interval-to-include-each-query/
裸的线段树题,还有也可以离线处理排序做
我最初思路是用二分做,也不知道对不对
下面是仿照大佬的代码写的,代码写的确实可以
class Solution {
public:
vector minInterval(vector>& intervals, vector& queries) {
//两种解法:一种离线处理+排序
//另一种线段树,就是线段树模板题
int n = intervals.size(), q = queries.size();
vectorans(q), order(q);
//厉害的人写的代码就是简洁
for(int i = 0; i < q; ++i){
order[i] = i;
}
sort(order.begin(), order.end(), [&](int i,int j){
return queries[i] < queries[j];
});
sort(intervals.begin(), intervals.end());
set>se;
int index = -1;
for(int i:order){
int qi = queries[i];
while(index + 1 < n && intervals[index + 1][0] <= qi){
se.insert(make_pair(intervals[index + 1][1] - intervals[index + 1][0] + 1, intervals[index + 1][1]));
index++;
}
while(!se.empty() && se.begin() -> second < qi){
se.erase(se.begin());
}
if(se.empty()){
ans[i] = -1;
}else{
ans[i] = se.begin() -> first;
}
}
return ans;
}
};
leetcode第 240 场周赛
总结:这次确实需要点时间,我觉得一个半小时对于我来说是不够的
5750. 人口最多的年份
https://leetcode-cn.com/problems/maximum-population-year/
简单暴力模拟
class Solution {
public:
int num[3005];
int maximumPopulation(vector<vector<int>>& logs) {
int len = logs.size();
memset(num, 0, sizeof(num));
for(int i = 0;i < len;++i){
for(int j = logs[i][0]; j < logs[i][1];++j){
num[j]++;
}
}
int MAX = 0;
int ans = 0;
for(int i = 1950;i <= 2050;++i){
if(num[i] > MAX){
ans = i;
MAX = num[i];
}
}
return ans;
}
};
5751. 下标对中的最大距离
https://leetcode-cn.com/problems/maximum-distance-between-a-pair-of-values/
两个指针移就行,算是一种模拟吧
class Solution {
public:
int maxDistance(vector<int>& num1, vector<int>& num2) {
int len1 = num1.size();
int len2 = num2.size();
int i = 0, j = 0;
int MAX = -1;
while(i < len1){
while(j < len2 && num1[i] <= num2[j]){
j++;
}
MAX = max(MAX, j - i);
i++;
}
if(MAX != 0){
MAX--;
}
return MAX;
}
};
5752. 子数组最小乘积的最大值
https://leetcode-cn.com/problems/maximum-subarray-min-product/
其实我已经想到了一种解法就是每个数左右找第一个比当前数小的位置,求解这个范围内的和乘当前数就是结果,找出最大值就行。
但是是O(n^2)的复杂度,所以需要优化,我主要忘了找第一个小的可以用单调栈,这样就可以优化到O(n)
class Solution {
public:
typedef long long LL;
const LL mod = 1e9 + 7;
LL sum[100005];
int left[100005];
int right[100005];
int maxSumMinProduct(vector<int>& num) {
memset(sum, 0, sizeof(sum));
memset(left, 0, sizeof(left));
memset(right, 0, sizeof(right));
num.insert(num.begin(), 0);
num.push_back(0);
int len = num.size();
sum[0] = num[0];
for(int i = 1;i < len;++i){
sum[i] = sum[i - 1] + num[i];
}
stack<int>sta1;
//找第一个小于的数,应该用单调栈
for(int i = 0;i < len;++i){
while(!sta1.empty() && num[sta1.top()] > num[i]){
right[sta1.top()] = i;
sta1.pop();
}
sta1.push(i);
}
stack<int>sta2;
for(int i = len - 1;i >= 0;--i){
while(!sta2.empty() && num[sta2.top()] > num[i]){
left[sta2.top()] = i;
sta2.pop();
}
sta2.push(i);
}
// for(int i = 0;i < len;++i){
// cout << left[i] << " ";
// }
// cout << endl;
// for(int i = 0;i < len;++i){
// cout << right[i] << " ";
// }
// cout << endl;
LL MAX = -1;
for(int i = 1;i < len - 1;++i){
MAX = max(MAX, num[i] * (sum[right[i] - 1] - sum[left[i]]));
}
return (int)(MAX % mod);
}
};
5753. 有向图中最大颜色值
https://leetcode-cn.com/problems/largest-color-value-in-a-directed-graph/
这里我以为dfs搜索有效路径,绝对可以,但是没想到居然超时了,确实复杂度不太好计算;
最后解法就是:
拓扑排序+动态规划
首先对图进行拓扑排序,假设i点的拓扑序在u点之前,dp[i][j]代表了i点之前的所有路径中j颜色的最大值,最后的状态转移方程如下:
dp[u][j] = max(dp[u][j], dp[i][j] + (colors[u] - ‘a’ == j))
class Solution {
public:
int rudu[100005];
int dp[100005][30];
map<int, vector<int>>graph;
int largestPathValue(string colors, vector<vector<int>>& edges) {
memset(rudu, 0, sizeof(rudu));
memset(dp,0,sizeof(dp));
int n = colors.size();
int m = edges.size();
for(int i = 0;i < m;++i){
rudu[edges[i][1]]++;
graph[edges[i][0]].push_back(edges[i][1]);
}
queue<int>que;
int cnt = 0;
for(int i = 0;i < n;++i){
if(rudu[i] == 0){
que.push(i);
dp[i][colors[i] - 'a']++;
cnt++;
}
}
while(!que.empty()){
int now_id = que.front();
que.pop();
int len = graph[now_id].size();
for(int i = 0;i < len;++i){
int next_id = graph[now_id][i];
for(int j = 0;j < 26;++j){
dp[next_id][j] = max(dp[next_id][j], dp[now_id][j] + (colors[next_id] - 'a' == j));
}
rudu[next_id]--;
if(rudu[next_id] == 0){
que.push(next_id);
cnt++;
}
}
}
if(cnt != n){
return -1;
}
int MAX = -1;
for(int i = 0;i < n;++i){
for(int j = 0;j < 26;++j){
MAX = max(MAX, dp[i][j]);
}
}
return MAX;
}
};
leetcode第 241 场周赛
5759. 找出所有子集的异或总和再求和
https://leetcode-cn.com/problems/sum-of-all-subset-xor-totals/
暴力
class Solution {
public:
int sum = 0;
void dfs(vector<int>& nums, int id, int cnt, int res){
if(nums.size() - id < cnt){
return ;
}
if(cnt == 0){
sum += res;
return ;
}
int len = nums.size();
for(int i = id + 1;i < len;++i){
dfs(nums, i, cnt - 1, res ^ nums[i]);
//cout << sum << endl;
}
return ;
}
int subsetXORSum(vector<int>& nums) {
sum = 0;
int len = nums.size();
for(int i = 0;i < len;++i){
dfs(nums,-1,i + 1,0);
}
return sum;
}
};
5760. 构成交替字符串需要的最小交换次数
https://leetcode-cn.com/problems/minimum-number-of-swaps-to-make-the-binary-string-alternating/
哎,这道题我一直想贪心移动,一直没想到很好的解法,原来是从结果出发,有点难想到啊 😭, 最终的结果就是两种,不是010101010…就是10101010…,这样 的话,比较不一样的个数,结果除以2就是需要交换的次数
class Solution {
public:
int minSwaps(string s) {
int len = s.size();
int zero = 0;
int one = 0;
for(int i = 0;i < len;++i){
if(s[i] == '0') zero++;
if(s[i] == '1') one++;
}
if(abs(zero - one) > 1)
return -1;
int res = 0x3f3f3f3f;
//无非就两种结果,01010101...., 或者是10101010.....
int cnt = 0;
for(int i = 0;i < len;++i){
if(('0' + i % 2) != s[i]) cnt++;
}
if(cnt % 2 == 0)
res = min(res, cnt / 2);
cnt = 0;
for(int i = 0;i < len;++i){
if(('0' + (i + 1) % 2) != s[i]) cnt++;
}
if(cnt % 2 == 0)
res = min(res, cnt / 2);
return res;
}
};
5761. 找出和为指定值的下标对
https://leetcode-cn.com/problems/finding-pairs-with-a-certain-sum/
这道题很简单,就做一个hash
class FindSumPairs {
public:
vector<int>a,b;
map<int,int>mk;
FindSumPairs(vector<int>& nums1, vector<int>& nums2) {
a = nums1;
b = nums2;
int len = b.size();
for(int i = 0;i < len;++i){
mk[b[i]]++;
}
}
void add(int index, int val) {
mk[b[index]]--;
b[index] += val;
mk[b[index]]++;
}
int count(int tot) {
int len = a.size();
int num = 0;
for(int i = 0;i < len;++i){
num += mk[tot - a[i]];
}
return num;
}
};
/**
* Your FindSumPairs object will be instantiated and called as such:
* FindSumPairs* obj = new FindSumPairs(nums1, nums2);
* obj->add(index,val);
* int param_2 = obj->count(tot);
*/
5762. 恰有 K 根木棍可以看到的排列数目
https://leetcode-cn.com/problems/number-of-ways-to-rearrange-sticks-with-k-sticks-visible/
这道题一看就是打表找规律,都是因为第二题导致这道题没做,不然这次能做完。递归是真的慢,不能用递归写
https://blog.csdn.net/sxh759151483/article/details/83420939
class Solution {
public:
typedef long long LL;
const LL mod = 1e9 + 7;
LL num[1005][1005];
int rearrangeSticks(int n, int k) {
// int a[] = {1,2,3,4,5,6};
// int b[] = {0,0,0,0,0,0,0};
// b[5] = 1;
// while(next_permutation(a, a + 6)){
// // for(int i = 0;i < 5;++i){
// // cout << a[i] << " ";
// // }
// // cout << endl;
// int cnt = 0;
// int MAX = -1;
// for(int i = 0;i < 6;++i){
// if(a[i] > MAX){
// cnt++;
// MAX = max(MAX, a[i]);
// }
// }
// b[cnt]++;
// }
// for(int i = 1;i <= 6;++i){
// cout << b[i] << endl;
// }
num[1][1] = 1;
for(int i = 1;i <= n;++i){
num[i][0] = 0;
}
for(int i = 2;i <= n;++i){
num[i][i] = 1;
for(int j = 1;j < i;++j){
num[i][j] = (num[i - 1][j - 1] + 1LL * (i - 1) * num[i - 1][j] % mod) % mod;
}
}
return num[n][k];
}
};
leetcode第243场周赛
5772. 检查某单词是否等于两单词之和
https://leetcode-cn.com/problems/check-if-word-equals-summation-of-two-words/
简单题
class Solution {
public:
bool isSumEqual(string first, string second, string target) {
int x = 0, y = 0,z = 0;
for(int i = 0;i < first.size();++i){
x = x * 10 + first[i] - 'a';
}
for(int i = 0;i < second.size();++i){
y = y * 10 + second[i] - 'a';
}
for(int i = 0;i < target.size();++i){
z = z * 10 + target[i] - 'a';
}
return x + y == z;
}
};
5773. 插入后的最大值
https://leetcode-cn.com/problems/maximum-value-after-insertion/
简单模拟
class Solution {
public:
string maxValue(string s, int x) {
string res = s;
int index = s.size();
if(s[0] == '-'){
for(int i = 0;i < s.size();++i){
while(s[i] == '0' + x){
i++;
}
if(i < s.size() && s[i] > '0' + x){
index = i;
break;
}
}
}else{
for(int i = 0;i < s.size();++i){
while(s[i] == '0' + x){
i++;
}
if(i < s.size() && s[i] < '0' + x){
index = i;
break;
}
}
}
res.insert(index, 1, x + '0');
return res;
}
};
- 使用服务器处理任务
https://leetcode-cn.com/problems/process-tasks-using-servers/
真的烦这种模拟,写的我很恶心,
我已经想到用两个优先队列了,但是没想到得两个相互转换,只是用两个优先队列把样例给过了,其实还是有一些特殊情况没考虑,一个busy队列,一个空闲队列
用curtime表示当前时间
其实做模拟非常有必要提前规划好步骤,不然写的时候就一头雾水,步骤写好了,就可以再封装函数什么的了。
class Solution {
public:
typedef struct Node{
int tw;
int id;
bool operator<(const Node& a) const
{
if(tw == a.tw){
return id > a.id;
}
return tw > a.tw; //大顶堆
}
}Node;
vector<int> assignTasks(vector<int>& servers, vector<int>& tasks) {
vector<int>ve(tasks.size());
priority_queue<Node>busy;
priority_queue<Node>idle;
for(int i = 0;i < servers.size();++i){
Node node = (Node){servers[i], i};
idle.push(node);
}
int curtime = 0;
//将busy优先队列中tw<=curtime的空闲机器放到空闲队列中
auto release = [&](){
while(!busy.empty() && busy.top().tw <= curtime){
Node node = busy.top();
node.tw = servers[node.id];
idle.push(node);
busy.pop();
}
};
for(int i = 0;i < tasks.size();++i){
//当前时间保持最大的
curtime = max(curtime, i);
//这里就区分开,空闲就是空闲,busy就是busy,不像我写的算法,区分不开,十分混乱
release();
if(idle.empty()){
curtime = busy.top().tw;
release();
}
//这样就可以从idle中继续取任务了
Node node = idle.top();
node.tw = curtime + tasks[i];
idle.pop();
busy.push(node);
ve[i] = node.id;
}
return ve;
}
};
5775. 准时抵达会议现场的最小跳过休息次数
https://leetcode-cn.com/problems/minimum-skips-to-arrive-at-meeting-on-time/
dp动态规划就是将所有状态包含进来,我刚开始也是想把目标设为最小花费时间,因为时间不好作为状态,长度为10^8, 但是我又设了dp[i][0,1], 0, 1表示跳与不跳,后来这个感觉不需要状态转移, 就是没想到第二维可以是dp[i][j],j代表跳过次数,差一点点。。。
class Solution {
public:
typedef long long LL;
LL dp[1005][1005];
int minSkips(vector<int>& dist, int speed, int hoursBefore) {
int n = dist.size();
memset(dp, 0, sizeof(dp));
for(int i = 1;i <= n;++i){
dp[i][0] = dp[i - 1][0] + 1LL * ((dist[i - 1] + speed - 1) / speed) * speed;
//cout << dp[i][0] << endl;
for(int j = 1;j < i;++j){
LL ptr = 1LL * ((dist[i - 1] + dp[i - 1][j] + speed - 1) / speed) * speed;
//cout << j << " " << ptr << endl;
dp[i][j] = min(ptr, dp[i - 1][j - 1] + dist[i - 1]);
}
dp[i][i] = dp[i - 1][i - 1] + dist[i - 1];
}
// for(int i = 0;i <= n;++i){
// for(int j = 0;j <= n;++j){
// cout << dp[i][j] << " ";
// }
// cout << endl;
// }
int res = -1;
for(int i = 0;i <= n;++i){
if(dp[n][i] <= 1LL * hoursBefore * speed){
res = i;
break;
}
}
return res;
}
};