第 327 场周赛
比赛链接
Date: 2023-01-08
A 正整数和负整数的最大计数
暴力
复杂度分析
- 时间复杂度:\(O(n)\)
- 空间复杂度:\(O(1)\)
B 执行 K 次操作后的最大分数
使用二叉堆维护当前最大值即可。上取整时使用 (x + (3 - 1)) / 3 即可实现上取整操作。
复杂度分析
- 时间复杂度:\(O(k \log n)\)
- 空间复杂度:\(O(n)\)
C 使字符串总不同字符的数目相等
使用哈希表记录每个字符出现的次数,由于每个字符串中的种类数不超过 26,所以可以用 26*26 的双层遍历来枚举替换情况。枚举时,有两种方法:
- 构造哈希表的副本,然后修改后对比即可。这样写不容易写错。(C++ 实现)
- 如果交换的是相同的字母,则跳过。否则根据交换的字母,根据实际的哈希表中的情况计算交换后的种类数进行对比。(容易写错,python 实现)
|  | class Solution {
public:
    bool isItPossible(string word1, string word2) {
        unordered_map<char, int> h1, h2;
        for (auto c : word1) h1[c]++;
        for (auto c : word2) h2[c]++;
        for (int i = 0; i < 26; i++) {
            for (int j = 0; j < 26; j++) {
                char x = 'a' + i;
                char y = 'a' + j;
                if (h1.count(x) && h2.count(y)) {
                    auto h1_c = h1, h2_c = h2;
                    h1_c[x]--; h1_c[y]++;
                    h2_c[y]--; h2_c[x]++;
                    int a = 0, b = 0;
                    for (auto &[k, v] : h1_c) if (v != 0) a++;
                    for (auto &[k, v] : h2_c) if (v != 0) b++;
                    if (a == b) return true;
                }
            }
        }
        return false;
    }
};
 | 
 
|  | class Solution:
    def isItPossible(self, word1: str, word2: str) -> bool:
        h1, h2 = Counter(word1), Counter(word2)
        l1, l2 = len(h1), len(h2)
        for x in h1:
            for y in h2:
                if x == y:
                    if l1 == l2:
                        return True
                    continue
                # 计算交换操作之后的种类数
                nl1 = l1 - 1 if h1[x] == 1 else l1
                nl2 = l2 - 1 if h2[y] == 1 else l2
                nl1 = nl1 + 1 if h1[y] == 0 else nl1
                nl2 = nl2 + 1 if h2[x] == 0 else nl2
                if nl1 == nl2:
                    return True
        return False
 | 
 
 
 
复杂度分析
- 时间复杂度:\(O(C^4)\),优化后的方法二为 \(O(C^2)\)
- 空间复杂度:\(O(n)\)
D 过桥的时间
工人共有四种状态,每一种状态都存在优先级对比,大致可以分为两类:
- 在左右对岸等待的工人,优先级根据题目中给定进行计算
- 在搬起或者放下的工人,优先级根据完成时间来计算
因此,要设置四个优先队列来分别存储他们。当旧仓库还有货物或者右边还有人时,过程就需要继续:
- 首先,如果搬起或者放下的工人在此时已经完成,则将他们依次加入左边或者右边的等待队列。
- 然后,如果右边有人等待,则取优先级最低的工人过桥,过桥后放入左侧的处于「放下」状态的队列。
- 否则如果旧仓库还有货物,并且左侧有等待的工人,则取优先级最低的工人过桥,过桥后放入右侧处于「搬起」状态的队列,并使得旧仓库待搬运货物数量减一。
- 否则,此时没有人需要过桥,时间应该过渡到第一个处于「放下」或者「搬起」状态的工人切换状态的时刻。
按照上述过程模拟,直到结束即可。注意问题关注的是,最后一个回到左边的工人的到达时间,并不是最后放下货物的时间。
|  | class Solution {
public:
    using PII = pair<int, int>;
    int findCrossingTime(int n, int k, vector<vector<int>>& time) {
        auto cmp = [&](int x, int y) {
            int l = (time[x][0] + time[x][2]);
            int r = (time[y][0] + time[y][2]);
            return l != r ? l < r : x < y;
        };
        // 左边和右边的等待队列
        priority_queue<int, vector<int>, decltype(cmp)> L(cmp), R(cmp);
        // 左边「放下」状态队列和右边「搬起」状态队列,PII 的第一关键字是完成时间,第二关键字是工人ID
        priority_queue<PII, vector<PII>, greater<PII>> ql, qr;
        // 剩余待处理货物数量和当前时间
        int rest = n, cur = 0;
        for (int i = 0; i < k; i++) L.push(i);
        while (rest > 0 || qr.size() > 0 || R.size() > 0) {
            // 1. 如果搬起或者放下的工人在此时已经完成,则将他们依次加入左边或者右边的等待队列。
            while (qr.size() && qr.top().first <= cur) {
                R.push(qr.top().second);
                qr.pop();
            }
            while (ql.size() && ql.top().first <= cur) {
                L.push(ql.top().second);
                ql.pop();
            }
            // 如果右边有人等待,则取优先级最低的工人过桥,过桥后放入左侧的处于「放下」状态的队列。
            if (R.size() > 0) {
                int x = R.top(); R.pop();
                cur += time[x][2];
                ql.push({cur + time[x][3], x});
            } else if (L.size() > 0 && rest > 0) {
            // 否则如果旧仓库还有货物,并且左侧有等待的工人,则取优先级最低的工人过桥,过桥后放入右侧处于「搬起」状态的队列,并使得旧仓库待搬运货物数量减一。
                int x = L.top(); L.pop();
                cur += time[x][0];
                qr.push({cur + time[x][1], x});
                rest--;
            } else {
            // 否则,此时没有人需要过桥,时间应该过渡到第一个处于「放下」或者「搬起」状态的工人切换状态的时刻。
                int x = 1e9;
                if (qr.size()) x = min(x, qr.top().first);
                if (ql.size()) x = min(x, ql.top().first);
                if (x != 1e9) cur = max(cur, x);
            }
        }
        return cur;
    }
};
 | 
 
 
 
复杂度分析
- 时间复杂度:\(O(n\log k)\)
- 空间复杂度:\(O(n)\)
    本站总访问量 Loading 次
    本站总访客数 Loading 人