Leetcode 第243场周赛
Leetcode 第243场周赛
前两题简单。
第三题一个模拟,容易边界处理不好。
第四题dp,卡精度。
第一题
https://leetcode-cn.com/problems/check-if-word-equals-summation-of-two-words/
直接算就行。
class Solution {
public:
bool isSumEqual(string firstWord, string secondWord, string targetWord) {
int x1 = 0;
for(auto c:firstWord){
x1 = x1 * 10 + (c - 'a');
}
int x2 = 0;
for(auto c:secondWord){
x2 = x2 * 10 + (c - 'a');
}
int x3 = 0;
for(auto c:targetWord){
x3 = x3 * 10 + (c - 'a');
}
return x1 + x2 == x3;
}
};
第二题
https://leetcode-cn.com/problems/maximum-value-after-insertion/
- 正负要分情况讨论。
- 从左向右插入,找第一个比自己小,或者比自己大的位置。
- string insert的api总是记不住:
// 这两个用的比较多
区别就是单字节和字符串,前者可以重重复count次字符,后者就是直接插入一个字符串。
// insert(size_type index, size_type count, char ch)
s.insert(0, 1, 'E');
assert("Exmplr" == s);
// insert(size_type index, const char* s)
s.insert(2, "e");
assert("Exemplr" == s);
代码:
class Solution {
public:
string maxValue(string n, int x) {
int nn = n.size();
int tar_index = 0;
tar_index = nn;
if(n[0] == '-'){
for(int i = 1 ; i < nn ; ++i){
if(n[i] - '0' <= x) continue;
else {
tar_index = i;
break;
}
}
} else {
for(int i = 0 ; i < nn ; ++i){
if(n[i] - '0' >= x) continue;
else {
tar_index = i;
break;
}
}
}
if(tar_index == nn) n.push_back(x + '0');
else n.insert(tar_index, 1, x + '0');
return n;
}
};
第三题
https://leetcode-cn.com/problems/process-tasks-using-servers/
大概思路是维护两个堆,第一个是可以用的服务器(idle),第二个是正在被使用的服务器(busy)。两边来回对调。
这个题没必要自定义排序,C++pair是自带排序的,先比较第一个,再比较第二个。所以小顶堆用greater<>或者大顶堆用less<>就可以了。
数据存的分别是:idle存权值w和下标idx,busy存等待时间t和idx。两边交换依靠idx唯一确定服务器。
然后是注意考虑一个堆为空的情况。
最后是时间的更新,不用循环每次+1,只要分情况就可以:
- idle为空,这时候time要一直等到最快一个完成才行,所以直接等过去就就好。
- busy为空,这时候直接等于当前下标最小的任务即可。
- 普通情况,应该是等于前面二者之间最小的那个。因为事件是按顺序发生的,如果某个该发生的事件时间被跳过去,后面的事件可能就都错乱了。所以应该先处理时间最小的那个。
class Solution {
public:
vector<int> assignTasks(vector<int>& servers, vector<int>& tasks) {
int n = servers.size();
int m = tasks.size();
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> idle_server_pool;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> busy_server_pool;
for(int i = 0 ; i < n ; ++i){
idle_server_pool.push(make_pair(servers[i], i));
}
int cur_time = 0;
vector<int> ret(m, 0);
int i = 0;
while(i < m){
if(idle_server_pool.empty()) cur_time = busy_server_pool.top().first;
else if (busy_server_pool.empty()) cur_time = i;
else cur_time = min(i, busy_server_pool.top().first);
while(!busy_server_pool.empty() && busy_server_pool.top().first <= cur_time){
idle_server_pool.push(make_pair(servers[busy_server_pool.top().second], busy_server_pool.top().second));
busy_server_pool.pop();
}
while(i < m && cur_time >= i && !idle_server_pool.empty()){
ret[i] = idle_server_pool.top().second;
busy_server_pool.push(make_pair(cur_time + tasks[i], idle_server_pool.top().second));
idle_server_pool.pop();
++i;
}
}
return ret;
}
};
第四题
https://leetcode-cn.com/problems/minimum-skips-to-arrive-at-meeting-on-time/
这个题是一个中等难度的dp
题解讲的很好,理解起来也不难。
其中有三个点比较难
- 下面代码的注释,是两种特殊情况,即跳跃次数为0和跳跃次数为1的情况。转移时必须注意。
- 初始化的问题,全部为INT_MAX。但是
dp[0][0]
应该是0 - 卡精度的问题,eps的使用方法
代码
class Solution {
public:
const double eps = 1e-9;
int minSkips(vector<int>& dist, int speed, int hoursBefore) {
int n = dist.size();
vector<vector<double>> dp(n + 1, vector<double>(n + 1,INT_MAX));
dp[0][0] = 0;
for(int i = 1 ; i <= n ; ++i){
for(int j = 0 ; j <= i ; ++j){
if(j != 0){
// 当跳跃次数为0时,不能从「上次跳跃」转移过来
// 此次转移为:上次跳跃
dp[i][j] = min(dp[i][j], dp[i - 1][j - 1] + dist[i - 1]/(double)speed);
}
if(j != i){
// 当跳跃次数与路的数量一致时,每一段路都跳跃。此时不能从「上次不跳跃」转移过来
// 此次转移为:上次不跳跃
dp[i][j] = min(dp[i][j], ceil(dp[i - 1][j] + dist[i - 1]/(double)speed - eps));
}
}
}
for(int j = 0 ; j <= n ; ++j){
if(dp[n][j] <= hoursBefore) return j;
}
return -1;
}
};