zoukankan      html  css  js  c++  java
  • 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;
        }
    }
    

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

  • 相关阅读:
    花匠
    积木
    Hello world
    老鼠走迷宫全部路径
    今天下午选做题目
    整数高精度运算——加法
    博客启航
    解线性不定方程
    关于完全背包问题
    关于最小代价子母树
  • 原文地址:https://www.cnblogs.com/PanYuDi/p/15541744.html
Copyright © 2011-2022 走看看