• LeetCode双周赛#36


    1604. 警告一小时内使用相同员工卡大于等于三次的人

    题目链接

    题意

    给定两个字符串数组keyNamekeyTime,分别表示名字为keytime[i]的人,在某一天内使用员工卡的时间(格式为24小时制,"HH:MM")。你要找出一小时内使用员工卡大于等于3的人,名字按字典序升序排列。注意,"23:51"-"00:10"不被视为一小时内,因为系统记录的是某一天内的使用情况

    分析

    给每个人创建一个数组,记录所有的打卡时间,然后将每个人名字字符串映射到相应的打卡时间数组。有个坑点是,题目给定的打卡时间不一定是顺序的,需要排序。另外,考虑到是记录当天的打卡时间,不妨将所有"HH:MM"换算为分钟制,比如"06:12"换算为(372min),便于后续判断。

    class Solution {
    public:
        vector<string> alertNames(vector<string>& keyName, vector<string>& keyTime) {
            unordered_map<string, vector<int>> t;
            vector<string> ans;
            for (int i = 0; i < keyName.size(); i++) {
                string hours = keyTime[i].substr(0, 2);
                string minutes = keyTime[i].substr(3, 2);
                int dt = stoi(hours) * 60 + stoi(minutes);
                t[keyName[i]].push_back(dt);
            }
            for (auto&& curName : t) {
                vector<int> tt = curName.second;
                if (tt.size() <= 2) continue;
                sort(tt.begin(), tt.end());
                for (int i = 2; i < tt.size(); i++) {
                    if (tt[i] - tt[i - 2] <= 60) {
                        ans.push_back(curName.first);
                        break;
                    }
                }
            }
            sort(ans.begin(), ans.end());
            return ans;
        }
    };
    

    1605. 给定行和列的和求可行矩阵 #贪心 #稀疏矩阵

    题目链接

    题意

    你不知道矩阵里每个元素的具体值,但已知每一行的总和和每一列的总和,求该矩阵。

    分析

    思路参考自@Durant。从((0,0))元素出发,每到达一位置((x, y)),就判断当前位置对应的rowSum[x]colSum[x]最小值,假如这个最小值是​rowSum[x]​,那么就将该最小值直接放到ans[x][y]即可,将colSum[x] -= rowSum[x]; rowSum[x]=0;,对应的第(x)行其余元素全部置0,然后接下来移动到((x+1, y))。假如这个最小值是colSum[x],同理。直到最终到达最后一行最后一列元素,即可终止。

    class Solution {
    public:
        vector<vector<int>> restoreMatrix(vector<int>& rowSum, vector<int>& colSum) {
            int n = rowSum.size(), m = colSum.size();
            vector<vector<int>> ans(n, vector<int>(m, 0));
            int i = 0, j = 0;
            while (1) {
                if (i >= n || j >= m) break;
                int cur = min(rowSum[i], colSum[j]);
                ans[i][j] = cur;
                rowSum[i] -= cur; if (rowSum[i] == 0) i++;            
                colSum[j] -= cur; if (colSum[j] == 0) j++;
            }
            return ans;
        }
    };
    

    1606. 找到处理最多请求的服务器 #STL #任务分配 #模拟

    题目链接

    题意

    (k)个服务器(编号从(0)开始),每个服务器不能同时处理超过一个的请求。第 (i)个请求到达时,请求分配到服务器的规则有:

    • 若所有服务器都已被占据,那么该请求被舍弃(完全不处理)。

    • 如果第$ (i % k)$ 个服务器空闲,那么对应服务器会处理该请求。

    • 否则,将请求安排给下一个空闲的服务器(服务器构成一个环,必要的话可能从第 0 个服务器开始继续找下一个空闲的服务器)。

    给定一个 严格递增 的正整数数组 arrival ,其中arrival[i]表示第 $i $个任务的到达时间,和另一个数组 load ,其中 load[i] 表示第 $i $个请求的工作量(也就是服务器完成它所需要的时间)。你的任务是找到 最繁忙的服务器 。最繁忙定义为一个服务器处理的请求数是所有服务器里最多的。要返回包含所有 最繁忙服务器 序号的列表,你可以以任意顺序返回这个列表。

    样例

    分析

    由于到达时间是(1e9)数量级,不可能直接枚举时间。我们应该用枚举“请求”的到达时间,如何维护服务器的工作状态?我们可以通过优先级队列,将工作中的服务器及对应的工作结束时间放到该队列中,工作时间结束得早,自然地就更早地放在队列队首或者弹出队列。怎么得知哪些服务器空闲?用(set)维护当前空闲服务器编号,之所以需要其自动排序的功能,是因为请求时是先从大到小寻找合适的编号的。由于(set)内部元素是顺序排列,那么我们自然通过二分查找到当前合适的服务器编号。这里,注意一下,对于(set)内部元素的查找,必须要用其自带的二分查找成员函数,否则会超时。具体原因戳此处的stackoverflow,感谢网友~

    using PII = pair<int, int>;
    class Solution {
    public:
        vector<int> busiestServers(int k, vector<int>& arrival, vector<int>& load) {
            int n = arrival.size();
            vector<int> cnt(k, 0); //cnt[i]表示第i个服务器接收请求次数
            set<int> freeIdx; //表示当前空闲的服务器(set会对编号从小到大排序)
            priority_queue<PII, vector<PII>, greater<PII>> busy; //值小优先级高,维护最快结束的服务器。pair的键对应该服务器结束时间,值对应于服务器编号
            for (int i = 0; i < k; i++) freeIdx.emplace(i); //所有服务器空闲
            for (int i = 0; i < n; i++) {
                if (!freeIdx.empty()) {
                    auto it = freeIdx.lower_bound(i % k); //找到请求的服务器编号(大于等于)
                    int finish = arrival[i] + load[i], idx; //finish计算结束时间
                    if (it != freeIdx.end()) {
                        idx = *(it);
                        freeIdx.erase(it); //idx服务器不再空闲
                    }
                    else { //后面找不到,只能回到前面去找
                        idx = *(freeIdx.begin());
                        freeIdx.erase(freeIdx.begin()); 
                    }
                    busy.push({ finish, idx }); //idx服务器不再空闲
                    cnt[idx]++;
                }
                if (i + 1 < n) {
                    while (!busy.empty() && busy.top().first <= arrival[i + 1]) { 
                        //如果某服务器工作结束时间比下一个请求的到达时间早,则
                        freeIdx.emplace(busy.top().second);//更新空闲服务器
                        busy.pop();
                    }
                }
            }
            int most = -1; vector<int> ans;
            for (int i = 0; i < k; i++) most = max(most, cnt[i]);
            for (int i = 0; i < k; i++) if (cnt[i] == most) ans.push_back(i);
            return ans;
        }
    };
    
  • 相关阅读:
    [HTML]HTML5实现可编辑表格
    [xcode]instruments来检验你的app
    [xcode]Xcode查找函数(方法)调用及被调用
    [工具][windows][visualStudio][充电]番茄助手vaassist常见用法
    [算法]判断一个数是不是2的N次方
    [Ogre]纹理设置
    C++中的类型重定义
    [STL]set/multiset用法详解[自从VS2010开始,set的iterator类型自动就是const的引用类型]
    [Ogre][地形][原创]基于OgreTerrain的地形实现
    PHP模板引擎Smarty内建函数section,sectionelse用法详解
  • 原文地址:https://www.cnblogs.com/J-StrawHat/p/13773346.html
Copyright © 2020-2023  润新知