1604. 警告一小时内使用相同员工卡大于等于三次的人 #哈希表 题意 给定两个字符串数组keyName和keyTime,分别表示名字为keytime[i]的人,在某一天 内使用员工卡的时间(格式为24小时制,"HH:MM")。你要找出一小时内使用员工卡大于等于3的人,名字按字典序升序排列。注意,"23:51"-"00:10"不被视为一小时内,因为系统记录的是某一天内的使用情况
分析 给每个人创建一个数组,记录所有的打卡时间,然后将每个人名字字符串映射到相应的打卡时间数组。有个坑点是,题目给定的打卡时间不一定是顺序的,需要排序。另外,考虑到是记录当天的打卡时间,不妨将所有"HH:MM"换算为分钟制,比如"06:12"换算为372 m i n 372min 372 min ,便于后续判断。
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 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 ) (0,0) ( 0 , 0 ) 元素出发,每到达一位置( x , y ) (x, y) ( x , y ) ,就判断当前位置对应的rowSum[x]与colSum[x]的最小值 ,假如这个最小值是rowSum[x],那么就将该最小值直接放到ans[x][y]即可,将colSum[x] -= rowSum[x]; rowSum[x]=0;,对应的第x x x 行其余元素全部置0 ,然后接下来移动到( x + 1 , y ) (x+1, y) ( x + 1 , y ) 。假如这个最小值是colSum[x],同理。直到最终到达最后一行最后一列元素,即可终止。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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 k k 个服务器(编号从0 0 0 开始),每个服务器不能同时处理超过一个的请求。第i i i 个请求到达时,请求分配到服务器的规则有:
若所有服务器都已被占据,那么该请求被舍弃(完全不处理)。
如果第$ (i % k)$ 个服务器空闲,那么对应服务器会处理该请求。
否则,将请求安排给下一个空闲的服务器(服务器构成一个环,必要的话可能从第 0 个服务器开始继续找下一个空闲的服务器)。
给定一个 严格递增 的正整数数组 arrival ,其中arrival[i]表示第 $i $个任务的到达时间,和另一个数组 load ,其中 load[i] 表示第 $i $个请求的工作量(也就是服务器完成它所需要的时间)。你的任务是找到 最繁忙的服务器 。最繁忙定义为一个服务器处理的请求数是所有服务器里最多的。要返回包含所有 最繁忙服务器 序号的列表,你可以以任意顺序返回这个列表。
样例 分析 由于到达时间是1 e 9 1e9 1 e 9 数量级,不可能直接枚举时间。我们应该用枚举“请求”的到达时间,如何维护服务器的工作状态?我们可以通过优先级队列,将工作中的服务器及对应的工作结束时间 放到该队列中,工作时间结束得早,自然地就更早地放在队列队首或者弹出队列。怎么得知哪些服务器空闲?用s e t set se t 维护当前空闲服务器编号,之所以需要其自动排序的功能,是因为请求时是先从大到小寻找合适的编号的。由于s e t set se t 内部元素是顺序排列,那么我们自然通过二分查找到当前合适的服务器编号。这里,注意一下,对于s e t set se t 内部元素的查找,必须要用其自带的二分查找成员函数,否则会超时。具体原因戳此处的stackoverflow ,感谢网友~
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 37 38 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 ) ; set<int > freeIdx; priority_queue<PII, vector<PII>, greater<PII>> busy; 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; if (it != freeIdx.end ()) { idx = *(it); freeIdx.erase (it); } else { idx = *(freeIdx.begin ()); freeIdx.erase (freeIdx.begin ()); } busy.push ({ finish, 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; } };