力扣266场周赛
Posted 算法与编程之美
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了力扣266场周赛相关的知识,希望对你有一定的参考价值。
1 问题
5918. 统计字符串中的元音子字符串
子字符串 是字符串中的一个连续(非空)的字符序列。元音子字符串 是 仅 由元音('a'、'e'、'i'、'o' 和 'u')组成的一个子字符串,且必须包含 全部五种 元音。给你一个字符串 word ,统计并返回 word 中 元音子字符串的数目 。
题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-vowel-substrings-of-a-string
示例:
输入:word = "aeiouu"
输出:2
解释:下面列出 word 中的元音子字符串(斜体加粗部分):
- "aeiouu"
- "aeiouu"
解析:该题题意就是找到由元音子字符串的个数,由于给出的数据范围n <= 100很小,所以可以直接采用暴搜来解决,遍历所有的子字符串,如果满足题意就直接在结果上加一;此处采用双for来遍历所有的子字符串。时间复杂度为O(n^2);
代码
const int N = 27; class Solution { public: bool snt[N], cnt[N]; int countVowelSubstrings(string word) { char bu[5] = {'a', 'e', 'i', 'o', 'u'}; int n = word.size(), res = 0; for (char c: bu) { int t = c - 'a'; snt[t] = true; } for (int i = 0; i < n; i ++){ int t = word[i] - 'a'; if (!snt[t]) continue; int num = 0, p = 0; memset(cnt, 0, sizeof cnt); for (int j = i; j < n; j ++) { int k = word[j] - 'a'; if (!snt[k]) break; if (!cnt[k]) { cnt[k] = true; p ++; } if (p >= 5) num ++; } res += num; } return res; } }; |
5919. 所有子字符串中的元音
给你一个字符串 word ,返回 word 的所有子字符串中 元音的总数 ,元音是指 'a'、'e'、'i'、'o' 和 'u' 。子字符串 是字符串中一个连续(非空)的字符序列。注意:由于对 word 长度的限制比较宽松,答案可能超过有符号 32 位整数的范围。计算时需当心。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/vowels-of-all-substrings
示例;
输入:word = "aba"
输出:6
解释:所有子字符串是:"a"、"ab"、"aba"、"b"、"ba" 和 "a" 。- "b" 中有 0 个元音- "a"、"ab"、"ba" 和 "a" 每个都有 1 个元音- "aba" 中有 2 个元音,因此,元音总数 = 0 + 1 + 1 + 1 + 1 + 2 = 6 。
解析:此题与第一题有些类似,不过该题是要求出包含元音子字符串的元音的个数总和,此题不可以采用暴搜,数据范围为1e5,否则会tle;不过此题可以反过来想,要求我们找到包含元音子字符串, 那么我们可以找到每一个元音字符,然后求出它所能构成的子字符串的数量即可。
例如 babe 找到元音字符’a’、’e’ 分别位于1、3的位置;对于’a’来说,他所能构成的包含自身的子字符串的数量为,a左边的个数乘以右边个数!解释:左边部分时即为b, 右边部分为be,而右边部分可以选0个、1个、2个 (注意题目中要求为连续的子字符串) 所以有三种,同理左边部分有两种,所有总共包含a的子字符串数量为2*3 = 6种。
代码
class Solution { public: typedef long long LL; long long countVowels(string word) { LL res = 0ll; int n = word.size(); for (int i = 0; i < n; i ++ ) { if (word[i] == 'a' || word[i] == 'e' || word[i] == 'i' || word[i] == 'o' || word[i] == 'u') { res = res + (LL)(i + 1) * (n - i); } } return res; } }; |
5920. 分配给商店的最多商品的最小值
给你一个整数 n ,表示有 n 间零售商店。总共有 m 种产品,每种产品的数目用一个下标从 0 开始的整数数组 quantities 表示,其中 quantities[i] 表示第 i 种商品的数目。
你需要将 所有商品 分配到零售商店,并遵守这些规则:
一间商店 至多 只能有 一种商品 ,但一间商店拥有的商品数目可以为 任意 件。
分配后,每间商店都会被分配一定数目的商品(可能为 0 件)。用 x 表示所有商店中分配商品数目的最大值,你希望 x 越小越好。也就是说,你想 最小化 分配给任意商店商品数目的 最大值 。请你返回最小的可能的 x 。
来源:力扣(LeetCode)
链接:
https://leetcode-cn.com/problems/minimized-maximum-of-products-distributed-to-any-store
示例;
输入:n = 6, quantities = [11,6]
输出:3
解释: 一种最优方案为:- 11 件种类为 0 的商品被分配到前 4 间商店,分配数目分别为:2,3,3,3 。- 6 件种类为 1 的商品被分配到另外 2 间商店,配数目分别为:3,3 。分配给所有商店的最大商品数目为 max(2, 3, 3, 3, 3, 3) = 3 。
来源:力扣(LeetCode)
链接:
https://leetcode-cn.com/problems/minimized-maximum-of-products-distributed-to-any-store
解析:此题的题意为给出quantities.size()个数,每一个数可以平摊到n个商店中的一些商店(或者全部)当中(解释:如果k平摊到m个商店当中, 那么每个商店的取值就为m/k或者ceil(m/k) ),但是每一个商店只能平摊quantities的某一个数,最后求最大值的最小;
此题有两种思考方式:
第一种就是贪心去模拟,每一次贪心的取最大的quantities[i],然后分摊商店的个数+1,进行分摊操作。其实也就是去模拟整个过程,但是此题模拟的时间复杂度很高,很容易超时。
第二种二分,可以注意到该题的数据范围为1 <= quantities[i] <= 1e5,所以我们去枚举所有的分摊操作的可能性,就是每一个商店分摊的数量,最后判断每一个quantities[i]全部分配完毕后会不会超过n个商店的个数。此处枚举可以采用二分进行枚举; 时间复杂度为O(mlog1e5).
代码
const int N = 100010; class Solution { public: int m; bool check(vector<int>& quantities, int k, int n){ int num = 0; for (int i = 0; i < m; i ++) { num += ceil((double)quantities[i]/k); if (num > n) return false; } return true; } int minimizedMaximum(int n, vector<int>& quantities) { m = quantities.size(); int l = 1, r = 100000; while(l < r) { int mid = l + r >> 1; if (check(quantities, mid, n)) r = mid; else l = mid + 1; } return r; } }; |
5921. 最大化一张图中的路径价值
给你一张 无向 图,图中有 n 个节点,节点编号从 0 到 n - 1 (都包括)。同时给你一个下标从 0 开始的整数数组 values ,其中 values[i] 是第 i 个节点的 价值 。同时给你一个下标从 0 开始的二维整数数组 edges ,其中 edges[j] = [uj, vj, timej] 表示节点 uj 和 vj 之间有一条需要 timej 秒才能通过的无向边。最后,给你一个整数 maxTime 。合法路径 指的是图中任意一条从节点 0 开始,最终回到节点 0 ,且花费的总时间 不超过 maxTime 秒的一条路径。你可以访问一个节点任意次。一条合法路径的 价值 定义为路径中 不同节点 的价值 之和 (每个节点的价值 至多 算入价值总和中一次)。请你返回一条合法路径的 最大 价值。注意:每个节点 至多 有 四条 边与之相连。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-path-quality-of-a-graph
示例;
输入:values = [0,32,10,43], edges = [[0,1,10],[1,2,15],[0,3,10]], maxTime = 49
输出:75
解释:一条可能的路径为:0 -> 1 -> 0 -> 3 -> 0 。总花费时间为 10 + 10 + 10 + 10 = 40 <= 49 。访问过的节点为 0 ,1 和 3 ,最大路径价值为 0 + 32 + 43 = 75 。
解析:该题就是一个一般的图论问题,从0出发最终回到0,且途径的时间不超过给出的最大时间限制;此题注意到10 <= timej, maxTime <= 100、每个节点至多有四条边;所以说步数不会超过10次,采用深搜可以解决此题,不用担心会超时;用邻接表记录每一条边、时间、价值三种数据,然后dfs遍历所有可能,记录从0出发最终回到0点的最大价值。
代码
const int N = 4010, M = 1010; class Solution { public: int e[N], ne[N], w[N], idx, h[M], Times, res; bool snt[N]; void add(int a, int b, int c){ e[idx] = b; ne[idx] = h[a]; w[idx] = c; h[a] = idx ++; } void dfs(vector<int>& values, int time, int val, int value){ if (time >= Times) { if (time == Times && val == 0) res = max(res, value); return; } if (val == 0) res = max(res, value); int p = values[val]; values[val] = 0; for (int i = h[val]; i != -1; i = ne[i]) { int k = e[i], t = time + w[i]; dfs(values, t, k, value + values[k]); } values[val] = p; } int maximalPathQuality(vector<int>& values, vector<vector<int>>& edges, int maxTime) { Times = maxTime; memset(h, -1, sizeof h); for (auto ed: edges) { int s = ed[0], d = ed[1], c = ed[2]; add(s, d, c); add(d, s, c); } dfs(values, 0, 0, values[0]); return res; } }; |
2 总结
本博客是力扣266场周赛的题解,如果存在不懂的地方可以在评论区提出,这里会耐心解答!关注公众号:算法与编程之美,我们会不断的更新力扣周赛题解,codeforces题解等比赛题解。
实习编辑:李欣容
稿件来源:深度学习与文旅应用实验室(DLETA)
以上是关于力扣266场周赛的主要内容,如果未能解决你的问题,请参考以下文章