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/

  1. 正负要分情况讨论。
  2. 从左向右插入,找第一个比自己小,或者比自己大的位置。
  3. 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

题解讲的很好,理解起来也不难。

其中有三个点比较难

  1. 下面代码的注释,是两种特殊情况,即跳跃次数为0和跳跃次数为1的情况。转移时必须注意。
  2. 初始化的问题,全部为INT_MAX。但是dp[0][0]应该是0
  3. 卡精度的问题,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;
    }
};
posted @ 2021-05-31 00:16  Molinchn  阅读(81)  评论(0编辑  收藏  举报