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]
	

这是因为

  1. 当word[i]是元音字母时,考虑所有以dp[i]为结尾的子字符串,实际上包含了所有以word[i - 1]为结尾的子字符串,看成以word[i - 1]为结尾的子字符串再拼上一个word[i]再加上一个word[i]自身的单字符字符串,所有的子字符串都多了一个元音,所有再加上子字符串数量即可,即加上i +1
  2. 当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;
    }
}

这里第一次遇到这种题,以后遇到得多了再做更深刻的总结吧

posted @ 2021-11-11 20:41  秋雨清笛  阅读(18)  评论(0编辑  收藏  举报