Hippogriff's Blog
首页
C++
  • 算法
  • 数据结构
  • Leetcode
  • 操作系统
  • 计算机网络
  • MySQL
  • 深度学习
  • 网络
收藏
  • 醍醐灌顶
  • 句读
个人书单 (opens new window)
GitHub (opens new window)

Absm

什么也不会
首页
C++
  • 算法
  • 数据结构
  • Leetcode
  • 操作系统
  • 计算机网络
  • MySQL
  • 深度学习
  • 网络
收藏
  • 醍醐灌顶
  • 句读
个人书单 (opens new window)
GitHub (opens new window)
  • 算法

  • 数据结构

  • Leetcode

    • 滑窗专题
    • 回文串专题
    • 剑指offer 07 重建二叉树
    • LCCUP 2021被虐
    • Leetcode 51 - N皇后
    • Leetcode 79 单词搜索
    • Leetcode 1577 数的平方等于两数乘积的方法数
    • Leetcode 5602 将 x 减到 0 的最小操作数
    • Leetcode 第243场周赛
      • 第一题
      • 第二题
      • 第三题
      • 第四题
    • Leetcode 全排列小专题
  • 算法
  • Leetcode
Absm
2021-05-30
目录

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;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 第二题

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);
1
2
3
4
5
6
7
8
9
10

代码:

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;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 第三题

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;

    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# 第四题

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;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
编辑 (opens new window)
上次更新: 2021/06/03, 14:04:20
Leetcode 5602 将 x 减到 0 的最小操作数
Leetcode 全排列小专题

← Leetcode 5602 将 x 减到 0 的最小操作数 Leetcode 全排列小专题→

最近更新
01
少年游·长安古道马迟迟
11-30
02
CMake基础命令
11-08
03
由浅入深剖析OAuth2.0的授权码模式
07-07
更多文章>
Theme by Vdoing | Copyright © 2019-2023 Murray Li | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×