266场周赛总结——又是两题寄的一天
今天又是两题寄的一天。这次的第三题是完全没思路,最后看了题解居然说是板子题。真菜啊,别人的板子题我居然一点思路都没。我何时才有能力ak一次啊
今天还是总结前三题,第四题就暂时不考虑了
2062. 统计字符串中的元音子字符串
word.length <=100,暴力双层循环直接秒杀了没啥好说的
2063. 所有子字符串中的元音
word.length <= 10^5说明不能搞n平方的算法了
想了一段时间,考虑使用动态规划
dp[i]代表以i结尾的子字符串的元音个数,可以得到以下关系
if word[i] is 元音字母
dp[i] = dp[i - 1] + i + 1
else
dp[i] = dp[i - 1]
这是因为
- 当word[i]是元音字母时,考虑所有以dp[i]为结尾的子字符串,实际上包含了所有以word[i - 1]为结尾的子字符串,看成以word[i - 1]为结尾的子字符串再拼上一个word[i]再加上一个word[i]自身的单字符字符串,所有的子字符串都多了一个元音,所有再加上子字符串数量即可,即加上i +1
- 当word[i]不是元音字母时,还是看成上一个字符结尾的所有子字符串拼接上自己,没有新增元音字符,所以dp[i] = dp[i - 1]
class Solution {
boolean isVowel(Character c) {
return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}
public long countVowels(String word) {
if(word.length() == 0) {
return 0;
}
long[] dp = new long[word.length()];
long[] dpSub = new long[word.length()];
dp[0] = isVowel(word.charAt(0))?1:0;
dpSub[0] = 1;
long res = dp[0];
for(int i = 1; i < word.length(); i++) {
if(isVowel(word.charAt(i))) {
dp[i] = dp[i - 1] + dpSub[i - 1] + 1;
} else {
dp[i] = dp[i - 1];
}
dpSub[i] = dpSub[i - 1] + 1;
res += dp[i];
}
return res;
}
}
2064. 分配给商店的最多商品的最小值
打比赛时一点思路没有,最后写了个暴力搜索上去果不其然超时了
这种双极值条件的题是典型的二分板子题,可以分成两个部分
1. 先确定一个最小值,这个最小值在外层循环用二分搜索
2. 在该最小值确定的条件下去判断能不能符合另一个条件的要求
这里的另一个条件即分配给最多的商店,因为分配的最小值min确定了,每种商品就可以用贪心的方法按最接近与这个min的去分配了
分配的房间数为
quantity / min + 1 (if quantity % min != 0)
quantity / min (if quantity % min== 0)
如果按小于min去分配按照以上算是肯定会分配到更多的房间,就更难达成所有商品分配完的目标了,因此这里贪心是正确的
所以只需要按照贪心去寻找二分的边界就可以了,伪代码如下
定义left,right
while(left <= right) {
计算mid
贪心法分配所有quantity
if 分配成功 说明mid还可以更小
right = mid - 1
else
left = mid + 1
}
以下为我写的代码
class Solution {
private boolean check(int maxArrange, int[] quantities, int n) {
int remain = n;
for(int quantity:quantities) {
int arrange = quantity / maxArrange;
if(quantity % maxArrange != 0) {
arrange++;
}
remain -= arrange;
if(remain < 0) {
return false;
}
}
return true;
}
public int minimizedMaximum(int n, int[] quantities) {
int l = 1;
int r = 1;
int res = Integer.MAX_VALUE;
for(int quantity:quantities) {
if(quantity > r) {
r = quantity;
}
}
while(l <= r) {
int mid = (l + r) / 2;
if(check(mid, quantities, n)) {
if(mid < res) {
res = mid;
}
r = mid - 1;
} else {
l = mid + 1;
}
}
return res;
}
}
这里第一次遇到这种题,以后遇到得多了再做更深刻的总结吧