• [朝花夕拾] LeetCode每日一题


    值得一提:

    20220304 2104; 20220309 798; 20220330 1606;

    20220228 1601. 最多可达成的换楼请求数目

    方法一:DFS 枚举

    枚举所有换楼请求的选择与不选择两种情况,最后判断是否满足题意,时间复杂度为 O(2 ^ m),m 为请求个数,依题意 m <= 16,符合要求。

     1 #include <cstring> 
     2 
     3 const int N = 25;
     4 
     5 class Solution {
     6 public:
     7     int a[N][N], b[N];
     8     int dfs(int o, int x, int n, int m) {
     9         int res = 0;
    10         if (o == m) {
    11             int tot = 0;
    12             for (int i = 0; i < n; i++) {
    13                 for (int j = 0; j < m; j++)
    14                     tot += (b[j] ? a[j][i] : 0);
    15                 if (tot != 0) return 0;
    16             }
    17             return x;        
    18         }
    19         b[o] = 1;
    20         res = dfs(o + 1, x + 1, n, m);
    21         b[o] = 0;
    22         res = max(res, dfs(o + 1, x, n, m));
    23         return res;
    24     }
    25     int maximumRequests(int n, vector<vector<int>>& requests) {
    26         int m = requests.size();
    27         for (int i = 0; i < m; i++)
    28             a[i][requests[i][0]] += -1, a[i][requests[i][1]] += 1;
    29         memset(b, 0, sizeof(b));
    30         return dfs(0, 0, n, m); 
    31     }
    32 };

    其实不用转换为二维数组,可以节省空间,并且 DFS 过程中就可以维护是否满足条件而不需要最后用 for 循环判断,代码有优化空间。

    方法二:二进制位运算枚举

    由于对于请求只有选择与不选择两种可能,使用二进制位运算,会大幅精简代码,但需要再最后用 for 循环判断是否满足条件,故时间复杂度会达到 O(n * 2 ^ m)。

     1 const int N = 25;
     2 
     3 class Solution {
     4 public:
     5     int maximumRequests(int n, vector<vector<int>>& r) {
     6         int a[N], m = r.size(), ans = 0;
     7         for (int o = 0; o < (1 << m); o++) {
     8             memset(a, 0, sizeof(a));
     9             int res = 0;
    10             for (int i = 0; i < m; i++)
    11                 if (o & (1 << i))
    12                     a[r[i][0]]--, a[r[i][1]]++, res++;
    13             int tot = 0;
    14             for (int i = 0; i < n; i++)
    15                 tot += (a[i] == 0);
    16             if (tot == n) ans = max(res, ans);
    17         }
    18         return ans;
    19     }
    20 };

    其他:最小费用最大流

    由于数据量并不大,用网络流有点杀鸡用牛刀了。

    20220301 6. Z 字形变换

    方法:找规律构造

    对需要输出的 Z 字形矩阵进行编号,找出规律即可直接构造。

     1 class Solution {
     2 public:
     3     string convert(string s, int r) {
     4         string a;
     5         int l = s.length(), x = 0;
     6         if (r == 1) return s;
     7         for (int i = 0; i < r; i++) {
     8             int o = i;
     9             if (o >= l) return a;
    10             while (1) {
    11                 if (i != r - 1) {
    12                     a += s[o];
    13                     o += (r - i - 1) * 2;
    14                     if (o >= l) break;
    15                 }
    16                 if (i != 0) {
    17                     a += s[o];
    18                     o += i * 2;
    19                     if (o >= l) break;
    20                 }
    21             }
    22         }
    23         return a;
    24     }
    25 };

    注意 numRows 为 1 时在这里需要单独考虑。

    其他:官方也提供了二维矩阵模拟和压缩存储空间两种方法,但显然是构造最为简单。

    20220302 564. 寻找最近的回文数

    自己做的时候思路不太行,越做越麻烦。

    看了官方的题解,温习和新学到了很多 C++ 特别是新版的用法:

    > stoi, stol, to_string... 等字符串转换函数

    > rbegin(), rend() 反向迭代器同样适用于 string

    > i & 1 非常方便的区分奇数偶数的写法

    > for (int i : {...}) 以及 for (auto& i: list)

     1 class Solution {
     2 public:
     3     vector<long> getlist(const string& str) {
     4         int l = str.length();
     5         vector<long> list = {(long)pow(10, l - 1) - 1, (long)pow(10, l) + 1};
     6         long pre = stol(str.substr(0, (l + 1) / 2));
     7         for (int i : {pre - 1, pre, pre + 1}) {
     8             string pres = to_string(i);
     9             string o = pres + string(pres.rbegin() + (l & 1), pres.rend());
    10             list.push_back(stol(o));
    11         }
    12         return list;
    13     }
    14 
    15     string nearestPalindromic(string str) {
    16         long n = stol(str), ans = -1;
    17         const vector<long>& list = getlist(str);
    18         for (auto& i : list) {
    19             if (i != n) {
    20                 long a1 = abs(i - n), a2 = abs(ans - n);
    21                 if (ans == -1 || a1 < a2 || a1 == a2 && i < ans) 
    22                     ans = i;
    23             }
    24         }
    25         return to_string(ans);
    26     }
    27 };

    20220303 258. 各位相加

    方法一:暴力回溯

     1 class Solution {
     2 public:
     3     int work(int num) {
     4         if (num < 10) return num;
     5         int res = 0;
     6         while (num)
     7             res += num % 10, num /= 10;
     8         return work(res);
     9     }
    10     
    11     int addDigits(int num) {
    12         return work(num); 
    13     }
    14 };

    方法二:规律

    由于数据范围在 int 内,num 的位数不会超过 10,则在第一次相加后得到的 num 必然在 100 以内,所以我考虑用方法一打出 100 以内的表,这样就最多只需要一次相加。

    实际上这也并非题目要求的 O(1),但打完表之后我们惊喜地发现,结果是 1 ~ 9 的循环,答案也就不言而喻了。

    1 class Solution {
    2 public:
    3     int addDigits(int num) {
    4         return (num - 1) % 9 + 1; 
    5     }
    6 };

    20220304 2104. 子数组范围和

    在写线段树的我是真的没救了(

    方法一:暴力枚举

     1 class Solution {
     2 public:
     3     long long subArrayRanges(vector<int>& a) {
     4         long long n = a.size(), ans = 0;
     5         for (int i = 0; i < n; i++) {
     6             int mx = a[i], mi = a[i];
     7             for (int j = i + 1; j < n; j++) {
     8                 mx = max(mx, a[j]);
     9                 mi = min(mi, a[j]);
    10                 ans += mx - mi;
    11             }    
    12         }        
    13         return ans;
    14     }
    15 };

    方法二:单调栈

    假设区间 i ∈ [j, k] 中,且 a[i] 是区间所有元素中的最大值,则该数对最后的范围和贡献了 a[i] * (i - j) * (k - i);同理如果是最小值,则贡献值取负。

    如何求得上述区间?当且仅当 [j, i - 1] ∪ [i + 1, k] 所有元素均 < a[i],且 a[j - 1] > a[i], a[k + 1] > a[i],即分别求左右侧距离 a[i] 最近的比 a[i] 大的元素。

    求最近元素采用:单调栈。单调栈的特点就是栈里保存的元素是有序的,举个例子,对于 [6, 4, 3, 5, 4, 2],找最近的比目标大的元素:

    入栈 6;当前栈顶为 6,比 4 大,记录,入栈 4;当前栈顶为 4,比 3 大,记录,入栈 3;当前栈顶为 3,比 5 小,出栈;为 4,比 5 小,出栈;为 6,比 5 大,记录,入栈 5……以此类推。

    不难发现这个过程中,栈始终会保持从栈顶到栈底的元素依次递减,这种栈被称之为单调栈。

     1 class Solution {
     2 public:
     3     long long subArrayRanges(vector<int>& a) {
     4         int n = a.size();
     5         long long ans = 0;
     6         stack<int> s1, s2;
     7         vector<int> mil(n), mxl(n), mir(n), mxr(n);
     8         for (int i = 0; i < n; i++) {
     9             while (!s1.empty() && a[s1.top()] > a[i])
    10                 s1.pop();
    11             mil[i] = s1.empty() ? -1 : s1.top();
    12             s1.push(i);
    13             while (!s2.empty() && a[s2.top()] <= a[i])
    14                 s2.pop();
    15             mxl[i] = s2.empty() ? -1 : s2.top();
    16             s2.push(i);
    17         }
    18         s1 = s2 = stack<int>();
    19         for (int i = n - 1; i >= 0; i--) {
    20             while (!s1.empty() && a[s1.top()] >= a[i])
    21                 s1.pop();
    22             mir[i] = s1.empty() ? n : s1.top();
    23             s1.push(i);
    24             while (!s2.empty() && a[s2.top()] < a[i])
    25                 s2.pop();
    26             mxr[i] = s2.empty() ? n : s2.top();
    27             s2.push(i);
    28         }
    29         for (int i = 0; i < n; i++)
    30             ans += (long long)a[i] * (long long)((i - mxl[i]) * (mxr[i] - i) - (i - mil[i]) * (mir[i] - i));
    31         return ans;
    32     }
    33 };

    细节:元素可能相等,可以对其中一侧允许包含相等,另一侧不允许。

    20220305 521. 最长特殊序列 I

    方法:脑筋急转弯

    1 class Solution {
    2 public:
    3     int findLUSlength(string a, string b) {
    4         return a == b ? -1 : max(a.size(), b.size());
    5     }
    6 };

    20220306 2100. 适合打劫银行的日子

    方法:前缀和(LC官方写的是动态规划)

     1 class Solution {
     2 public:
     3     vector<int> goodDaysToRobBank(vector<int>& a, int t) {
     4         int n = a.size();
     5         vector<int> dec(n);
     6         vector<int> inc(n);
     7         for (int i = 1; i < n; i++) {
     8             if (a[i] <= a[i - 1])
     9                 dec[i] = dec[i - 1] + 1;
    10             if (a[n - i - 1] <= a[n - i])
    11                 inc[n - i - 1] = inc[n - i] + 1;
    12         }
    13         vector<int> ans;
    14         for (int i = t; i < n - t; i++) {
    15             if (dec[i] >= t && inc[i] >= t) {
    16                 ans.emplace_back(i);
    17             }
    18         }
    19         return ans;
    20     }
    21 };

    20220307 504. 七进制数

     1 class Solution {
     2 public:
     3     string convertToBase7(int num) {
     4         string ans;
     5         int x;
     6         if (num < 0) num = -num, ans.push_back('-');
     7         for (x = 1; x * 7 <= num; x *= 7);
     8         while (x) {
     9             int o = 0, i;
    10             for (i = 0; o + x <= num; i++, o += x);
    11             num -= o, x /= 7, ans.push_back((char)i + '0');
    12         } 
    13         return ans;
    14     }
    15 };

    20220308 2055. 蜡烛之间的盘子

    方法:预处理前缀和

    看起来像 DP,但其实不需要,预处理出每个位置左右侧最近的蜡烛位置以及前 i 个位置的蜡烛个数即可。

     1 class Solution {
     2 public:
     3     vector<int> platesBetweenCandles(string s, vector<vector<int>>& q) {
     4         int len = s.length();
     5         vector<int> ans, l(len), r(len), sum(len);
     6         sum[0] = s[0] == '|', l[0] = s[0] == '|' ? 0 : -1;
     7         for (int i = 1; i < len; i++) {
     8             sum[i] = sum[i - 1] + (s[i] == '|');
     9             l[i] = s[i] == '|' ? i : l[i - 1];
    10         }
    11         r[len - 1] = s[len - 1] == '|' ? len - 1 : -1;
    12         for (int i = len - 2; i >= 0; i--)
    13             r[i] = s[i] == '|' ? i : r[i + 1];
    14         int tot = q.size();
    15         for (int i = 0; i < tot; i++)
    16             if (l[q[i][1]] == -1 || r[q[i][0]] == -1) ans.push_back(0); 
    17             else ans.push_back(max(0, l[q[i][1]] - r[q[i][0]] + 1 - sum[q[i][1]] + (q[i][0] == 0 ? 0 : sum[q[i][0] - 1])));
    18         return ans;
    19     }
    20 };

    20220309 798. 得分最高的最小轮调

    方法:差分数组

    对于元素 a[i] = x,当其轮调后的新下标 j >= x 时,会得到 1 分,即得分下标范围为 [x, n - 1],共 n - x 个;不得分范围为 [0, x - 1],共 x 个。

    由于其初始下标为 i,轮调下标为 k,则新下标 j = (i - k + n) mod n,当且仅当 (i - k + n) mod n >= x 时得分,等价于 k <= (i - x + n) mod n;又得分下标共  n - x 个,故 k >= (i + 1) mod n。

    综上,当 i < x 时,i + 1 <= k <= i - x + n;当 i >= x 时,k >= i + 1 或 k <= i - x。

    创建数组 points,points[k] 表示轮调下标为 k 时的得分。对于 nums 的每个元素,直接将 points 的对应的得分下标范围所有元素 +1。完成后求得 points 中的最大值即可。这个过程本身和暴力一样也是 O(n ^ 2),但是由于所有的操作都是范围操作,使用差分数组即可降维。

    比如针对 i < x,我们需要将 [i + 1, i - x + n] 所有元素 +1,定义差分数组 diffs[k] = points[k] - points[k - 1],直接 diffs[i + 1]++, diffs[i - x + n]-- 即可,最后计算 diffs 的前缀和,即可还原 points 的数据。

    记得取模。

     1 class Solution {
     2 public:
     3     int bestRotation(vector<int>& nums) {
     4         int n = nums.size(), ans = 0, sum = 0, mx = 0;
     5         vector<int> diffs(n);
     6         for (int i = 0; i < n; i++) {
     7             int l = (i + 1) % n, r = (i - nums[i] + n + 1) % n;
     8             diffs[l]++, diffs[r]--; 
     9             if (l >= r) diffs[0]++;
    10         }
    11         for (int i = 0; i < n; i++)
    12             if (mx < (sum += diffs[i]))
    13                 mx = sum, ans = i;
    14         return ans;
    15     }
    16 };

    20220310. N 叉树的前序遍历

     1 class Solution {
     2 public:
     3     void dfs(const Node* root, vector<int> & res) {
     4         if (root == nullptr) {
     5             return;
     6         }
     7         res.emplace_back(root->val);
     8         for (auto & ch : root->children) {
     9             dfs(ch, res);
    10         }
    11     }
    12 
    13     vector<int> preorder(Node* root) {
    14         vector<int> res;
    15         dfs(root, res);
    16         return res;
    17     }
    18 };

    20220311 2049. 统计最高分的节点数目

    方法:DFS

    题目第一眼看起来好麻烦,其实其得分乘积很容易得出:左子树结点数 * 右子树结点数 * (总结点数 - 以该结点为根的子树结点数),把父结点关系数组转化为左右子树关系后再 DFS 就很容易求出来了。

     1 const int N = 1e5 + 5;
     2 
     3 class Solution {
     4     long long l[N], r[N], tl[N], tr[N], b[N];
     5 public:
     6     int dfs(int o) {
     7         if (!tl[o]) return 1;
     8         l[o] = dfs(tl[o]);
     9         if (tr[o]) r[o] = dfs(tr[o]);
    10         return l[o] + r[o] + 1;
    11     }
    12     int countHighestScoreNodes(vector<int>& p) {
    13         int n = p.size(), ans;
    14         long long mx = 0;
    15         for (int i = 1; i < n; i++)
    16             if (tl[p[i]]) tr[p[i]] = i;
    17             else tl[p[i]] = i;
    18         int root = dfs(0);
    19         for (int i = 0 ; i < n; i++) {
    20             for (auto &j : {&l[i], &r[i], &(b[i] = root - l[i] - r[i] - 1)})
    21                 if (!*j) *j = 1; 
    22             long long res = l[i] * r[i] * b[i];
    23             if (res > mx) mx = res, ans = 1;
    24             else if (res == mx) ans++;
    25         }
    26         return ans;
    27     }
    28 } s;

    其实求最大值的这个循环可以直接在 DFS 中完成,因为显然 DFS 每个结点也有且仅有一次遍历,在 return 前就可以进行比较了。

    20220312 590. N 叉树的后序遍历

     1 class Solution {
     2 public:
     3     void helper(const Node* root, vector<int> & res) {
     4         if (root == nullptr) {
     5             return;
     6         }
     7         for (auto & ch : root->children) {
     8             helper(ch, res);
     9         }
    10         res.emplace_back(root->val);
    11     }
    12 
    13     vector<int> postorder(Node* root) {
    14         vector<int> res;
    15         helper(root, res);
    16         return res;
    17     }
    18 };

    20220313 393. UTF-8 编码验证

     1 class Solution {
     2 public:
     3     bool validUtf8(vector<int>& data) {
     4         int cnt = 0;
     5         for(int x : data) {
     6             if((x >> 7) & 1) {
     7                 if((x >> 6) & 1) {
     8                     if((x >> 5) & 1) {
     9                         if((x >> 4) & 1) {
    10                             if((x >> 3) & 1) {
    11                                 return false;
    12                             } else {
    13                                 if(cnt) {
    14                                     return false;
    15                                 }
    16                                 cnt = 3;
    17                             }
    18                         } else {
    19                             if(cnt) {
    20                                 return false;
    21                             }
    22                             cnt = 2;
    23                         }
    24                     } else {
    25                         if(cnt) {
    26                             return false;
    27                         }
    28                         cnt = 1;
    29                     }
    30                 } else {
    31                     cnt--;
    32                 }
    33             } 
    34         }
    35 
    36         return cnt == 0;
    37     }
    38 };

    22020314 599. 两个列表的最小索引总和

     1 class Solution {
     2 public:
     3     vector<string> findRestaurant(vector<string>& list1, vector<string>& list2) {
     4         unordered_map<string, int> index;
     5         for (int i = 0; i < list1.size(); i++) {
     6             index[list1[i]] = i;
     7         }
     8 
     9         vector<string> ret;
    10         int indexSum = INT_MAX;
    11         for (int i = 0; i < list2.size(); i++) {
    12             if (index.count(list2[i]) > 0) {
    13                 int j = index[list2[i]];
    14                 if (i + j < indexSum) {
    15                     ret.clear();
    16                     ret.push_back(list2[i]);
    17                     indexSum = i + j;
    18                 } else if (i + j == indexSum) {
    19                     ret.push_back(list2[i]);
    20                 }
    21             }
    22         }
    23         return ret;
    24     }
    25 };

    20220315 2044. 统计按位或能得到最大值的子集数目

     1 class Solution {
     2 public:
     3     int countMaxOrSubsets(vector<int> const& nums) {
     4         const int n = nums.size(), maxsum = accumulate(nums.begin(), nums.end(), 0, bit_or<int>{});
     5         const auto dfs = [&] (auto&& dfs, int p = 0, int sum = 0) {
     6             if (sum == maxsum) return 1 << (n - p);
     7             if (n == p) return 0;
     8             assert(p < n);
     9             return dfs(dfs, p + 1, sum) + dfs(dfs, p + 1, sum | nums[p]);
    10         };
    11         return dfs(dfs);
    12     }
    13 };

    20220316 432. 全 O(1) 的数据结构

    方法:双向链表+哈希

     1 class AllOne {
     2     list<pair<unordered_set<string>, int>> l;
     3     unordered_map<string, list<pair<unordered_set<string>, int>> :: iterator> mp; 
     4 public:
     5     AllOne() {}
     6     
     7     void inc(string key) {
     8         if (mp.count(key)) {
     9             auto cur = mp[key], nxt = next(cur);
    10             if (nxt == l.end() || nxt->second > cur->second + 1) {
    11                 unordered_set<string> s({key});
    12                 mp[key] = l.emplace(nxt, s, cur->second + 1);
    13             }
    14             else {
    15                 nxt->first.emplace(key);
    16                 mp[key] = nxt;    
    17             }
    18             cur->first.erase(key);
    19             if (cur->first.empty())
    20                 l.erase(cur);
    21         } else {
    22             if (l.empty() || l.begin()->second > 1) {
    23                 unordered_set<string> s({key});
    24                 l.emplace_front(s, 1);
    25             } else {
    26                 l.begin()->first.emplace(key);
    27             }
    28             mp[key] = l.begin();    
    29         }
    30     }
    31     
    32     void dec(string key) {
    33         auto cur = mp[key];
    34         if (cur->second == 1) {
    35             mp.erase(key);
    36         } else {
    37             auto pre = prev(cur);
    38             if (cur == l.begin() || pre->second < cur->second - 1) {
    39                 unordered_set<string> s({key});
    40                 mp[key] = l.emplace(cur, s, cur->second - 1);
    41             } else {
    42                 pre->first.emplace(key);
    43                 mp[key] = pre;
    44             }
    45         }
    46         cur->first.erase(key);
    47         if (cur->first.empty()) {
    48             l.erase(cur);
    49         }
    50     }
    51     
    52     string getMaxKey() {
    53         return l.empty() ? "" : *l.rbegin()->first.begin();
    54     }
    55     
    56     string getMinKey() {
    57         return l.empty() ? "" : *l.begin()->first.begin();
    58     }
    59 };

    20220317 720. 词典中最长的单词

    方法一:排序+哈希

     1 class Solution {
     2 public:
     3     string longestWord(vector<string>& words) {
     4         sort(words.begin(), words.end(), [](const string &a, const string &b){
     5             return a.size() == b.size() ? a > b : a.size() < b.size();
     6         });
     7         string ans = "";
     8         unordered_set<string> s;
     9         s.emplace("");
    10         for (auto & word : words) {
    11             if (s.count(word.substr(0, word.size() - 1))) {
    12                 s.emplace(word);
    13                 ans = word;
    14             }
    15         }
    16         return ans;
    17     }
    18 };

    方法二:Trie 字典树

     1 class Trie {
     2     vector<Trie*> child;
     3     bool isEnd;
     4 public:
     5     Trie() {
     6         this->child = vector<Trie*>(26, nullptr);
     7         this->isEnd = 0;
     8     }
     9     void insert(const string& word) {
    10         Trie* node = this;
    11         for (const auto &ch : word) {
    12             int o = ch - 'a';
    13             Trie* nxt = node->child[o]; 
    14             if (node->child[o] == nullptr)
    15                 node->child[o] = new Trie();
    16             node = node->child[o];
    17         }
    18         node->isEnd = 1;
    19     }
    20     bool dfs(const string& word) {
    21         Trie* node = this;
    22         for (const auto &ch : word) {
    23             int o = ch - 'a';
    24             if (node->child[o] == nullptr || !node->child[o]->isEnd)
    25                 return 0;
    26             node = node->child[o];
    27         }
    28         return node != nullptr && node->isEnd;
    29     }
    30 };
    31 
    32 class Solution {
    33 public:
    34     string longestWord(vector<string>& words) {
    35         Trie t;
    36         for (const auto &word : words)
    37             t.insert(word);
    38         string ans = "";
    39         int mx = 0;
    40         for (const auto &word : words) {
    41             int l = word.size();
    42             if (t.dfs(word))
    43                 if (l > mx || l == mx && word < ans)
    44                 ans = word, mx = l;
    45         }
    46         return ans;
    47     }
    48 };

    中间因为准备毕设和复试中断了一段时间,现在恢复保护现场。

    20220329 2024. 考试的最大困扰度

    方法:双指针法

    和第 3 题差不多,完全不需要用到 DP。

     1 class Solution {
     2 public:
     3     int work(string s, int k) {
     4         int l = 0, r = 0, ans = 0, o = 0, len = s.length();
     5         while (r < len) {
     6             while (s[r] == 'T') r++;
     7             while (s[r] == 'F' && o < k)
     8                 r++, o++;
     9             ans = max(ans, r - l);
    10             while (o == k && s[r] == 'F')
    11                 if (s[l] == 'F') l++, o--;
    12                 else while (s[l] == 'T') l++;
    13         }
    14         return ans;
    15     }
    16     int maxConsecutiveAnswers(string s, int k) {
    17         int len = s.length();
    18         string t = s;
    19         for (int i = 0; i < len; i++)
    20             t[i] = (s[i] == 'F' ? 'T' : 'F');
    21         return max(work(s, k), work(t, k));   
    22     }
    23 };

    20220330 1606. 找到处理最多请求的服务器

    方法一:模拟

    直接按题意要求,从第 i % k 个服务器开始依次查询是否繁忙,同时维护每个服务器处理请求个数,时间复杂度为 O(n * k),不满足题意。

    方法:优先队列

    模拟过程有个问题在于,每次会扫描所有服务器判断是否繁忙,重复操作相当多;

    考虑将所有当前繁忙的服务器放入一个优先队列 priority_queue,按照处理结束时间从早到晚排序,每次接收一个新处理时,将所有结束时间早于该新处理开始时间的服务器取出,再放入一个空闲服务器的 set,再从 set 中取出大于 i % k 的服务器(主要服务器是环形,还要考虑绕一圈从服务器 0 开始的情况),这样每次查询都只有 log 的复杂度了,最后时间复杂度为 O(n log n) 或 O(n log k);

    一道不错的 STL 综合运用。

     1 class Solution {
     2 public:
     3     vector<int> busiestServers(int k, vector<int>& a, vector<int>& l) {
     4         set<int> avail;
     5         vector<int> tot(k), ans;
     6         priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> busy;
     7         int n = a.size();
     8         for (int i = 0; i < k; i++)
     9             avail.insert(i);
    10         for (int i = 0; i < n; i++) {
    11             while (!busy.empty() && busy.top().first <= a[i])
    12                 avail.insert(busy.top().second), busy.pop();
    13             if (avail.empty())
    14                 continue;
    15             auto o = avail.lower_bound(i % k);
    16             if (o == avail.end())
    17                 o = avail.begin();
    18             tot[*o]++;
    19             busy.emplace(a[i] + l[i], *o);
    20             avail.erase(o);
    21         }
    22         int mx = *max_element(tot.begin(), tot.end());
    23         for (int i = 0; i < k; i++)
    24             if (tot[i] == mx)
    25                 ans.push_back(i);
    26         return ans;
    27     }
    28 };

    20220331 728. 自除数

     1 class Solution {
     2 public:
     3     vector<int> selfDividingNumbers(int l, int r) {
     4         vector<int> ans;
     5         for (int i = l; i <= r; i++) {
     6             int o = i, x = i, nob = 0;
     7             while (x) {
     8                 if (!(x % 10) || o % (x % 10)) {
     9                     nob = 1;
    10                     break;
    11                 }
    12                 x /= 10;
    13             }
    14             if (!nob) ans.push_back(i);
    15         }
    16         return ans;
    17     }
    18 } s;
  • 相关阅读:
    Django继承user类来定制自己的user类
    pycharm下载 安装 使用
    360 so动态脱壳
    爱加密so保护简单脱壳测试
    菜鸟 学注册机编写之 “sha1”
    海海DRM视频保护解密流程分析
    通过CreateThreadpoolWait执行Shellcode
    .net学习--Fastjson反序列漏洞
    .net JavaScriptSerializer反序列化漏洞
    java web安全(自定义Classloader)--服务器端动态解析二进制class文件
  • 原文地址:https://www.cnblogs.com/jinkun113/p/15945270.html
Copyright © 2020-2023  润新知