天天看點

力扣266場周賽

1 問題

5918. 統計字元串中的元音子字元串

子字元串 是字元串中的一個連續(非空)的字元序列。元音子字元串 是 僅 由元音('a'、'e'、'i'、'o' 和 'u')組成的一個子字元串,且必須包含 全部五種 元音。給你一個字元串 word ,統計并傳回 word 中 元音子字元串的數目 。

示例:

輸入:word = "aeiouu"

輸出:2

解釋:下面列出 word 中的元音子字元串(斜體加粗部分):

- "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 位整數的範圍。計算時需當心。

示例;

輸入: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種。

    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);

5920. 配置設定給商店的最多商品的最小值

給你一個整數 n ,表示有 n 間零售商店。總共有 m 種産品,每種産品的數目用一個下标從 0 開始的整數數組 quantities 表示,其中 quantities[i] 表示第 i 種商品的數目。

你需要将 所有商品 配置設定到零售商店,并遵守這些規則:

一間商店 至多 隻能有 一種商品 ,但一間商店擁有的商品數目可以為 任意 件。

配置設定後,每間商店都會被配置設定一定數目的商品(可能為 0 件)。用 x 表示所有商店中配置設定商品數目的最大值,你希望 x 越小越好。也就是說,你想 最小化 配置設定給任意商店商品數目的 最大值 。請你傳回最小的可能的 x 。

輸入: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 。

解析:此題的題意為給出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;

    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 秒的一條路徑。你可以通路一個節點任意次。一條合法路徑的 價值 定義為路徑中 不同節點 的價值 之和 (每個節點的價值 至多 算入價值總和中一次)。請你傳回一條合法路徑的 最大 價值。注意:每個節點 至多 有 四條 邊與之相連。

輸入: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;

    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題解等比賽題解。

實習編輯:李欣容