LeetCode周赛325

1.到目标字符串的最短距离

题目

Solution

class Solution {
public:
    int closetTarget(vector<string>& words, string target, int startIndex) {
        int n = words.size();
        int ans = -1;
        for(int i = 0;i <= n/2;i++){//i为目标words与startIndex的相对位置
            if(words[(startIndex + i) % n] == target){
                ans = i;
                break;
            }
            if(words[(startIndex - i + n) % n] == target){
                ans = i;
                break;
            }
        }
        return ans;
    }
};

2.每种字符至少取 K 个

题目

Solution

class Solution {
public:
    int takeCharacters(string s, int k) {
        int n = s.size();
        int numsa = count(s.begin(),s.end(),'a');//串中a的个数
        int numsb = count(s.begin(),s.end(),'b');//串中b的个数
        int numsc = count(s.begin(),s.end(),'c');//串中c的个数
        if(numsa < k || numsb < k|| numsc < k) return -1;
        int a = numsa - k,b = numsb - k,c = numsc - k;
        vector<int> sum(3), check{a,b,c};
        int i,j,ans = INT_MAX;
        for(i = 0, j = 0;j < s.size();j++){
            sum[s[j] - 'a']++;
            if(sum[s[j] - 'a'] > check[s[j] - 'a']){
                while(sum[s[j] - 'a'] > check[s[j] - 'a']){
                    sum[s[i] - 'a']--;
                    i++;
                }
            }
            ans=min(n-(j-i+1),ans);
        }
        return ans;
    }
};

3.礼盒的最大甜蜜度

题目

Solution

这道题需要用到二分答案。
根据题意,我们需要在\(k\)\(price\)不同的糖果之中找到最大的甜蜜度。

分析题目随着甜蜜度的增加,我们可以选择的糖果数量越少,满足二分答案的使用。

每次二分得到的甜蜜度,然后判断能否拿到\(k\)个糖果满足二分得到的答案,不能则表明大了,能则再试试更大的数。

class Solution {
public:
    int maximumTastiness(vector<int>& price, int k) {
        sort(price.begin(),price.end());
        int n = price.size();
        int l = 0,r = 1e9;//二分边界
        auto check = [&](int u){
            int cnt = 1;//拿了几类糖果计数
            for(int i = 0,j = 0;j < n;j++){
                if(price[j] - price[i] >= u){//该糖果可以拿
                    cnt++;
                    i = j;
                }
            }
            return cnt < k;
        };
        while(l < r){//开始二分
            int mid = (l + r) / 2;
            if(check(mid)){//取大了
                r = mid;
            }else{
                l = mid+1;
            }
        }
        return l-1;
    }
};

4.好分区的数目

题目

Solution

这道题容易想到使用DP来解决,题目要求分组中元素之和不小于\(k\),我们可以先求其逆命题,求元素和小于\(k\)的划分,然后用总的能划分的分组数减去不符合要求的数量,得到最终的答案。
因为位置不同算作不同分组,可以只用求第一个组的元素和小于\(k\)的方案数,最后乘2就可以了。
变成逆命题后题目就可以用01背包求方案数来解决。

class Solution {
    const int MOD = 1e9+7;
public:
    int countPartitions(vector<int>& nums, int k) {
        if(accumulate(nums.begin(),nums.end(),0L) < 2*k) return 0;
        //dp
        vector<int> f(k+5,1);
        int ans = 1;
        for(int i = 1;i <= nums.size();i++){
            ans = (ans * 2) % MOD;
            for(int j = k - 1;j >= nums[i-1];j--){//dp方案数
                f[j] = (f[j] + f[j - nums[i-1]]) % MOD;
            }
        }
        return (ans - f[k-1]*2 + MOD) % MOD;
    }
};
posted @ 2022-12-31 15:59  TTS-S  阅读(18)  评论(0编辑  收藏  举报