LeetCode第 282 场周赛


T1

题目描述:给你一个字符串数组和一个字符串,统计字符串数组中有多少字符串的前缀与给定字符串相等。

思路:根据题意模拟即可

时间复杂度:\(O(\sum |s|)\)

参考代码:

class Solution {
public:
    int prefixCount(vector& words, string pref) {
        int res = 0;
        for(auto& word : words){
            if(word.size() < pref.size()) continue;
            string s = word.substr(0 , pref.size());
            if(s == pref) ++res;
        }
        return res;
    }
};

T2

题目描述:给你两个字符串,每次可以向两个字符串中的一个填加任意字符,问将两个字符串中的各种字符的数量变相等所需要的最小操作次数。

思路:显然最小操作次数就是两个字符串中各种字符的数量的差的绝对值的和

时间复杂度:\(O(n)\)

参考代码:

class Solution {
public:
    int minSteps(string s, string t) {
        vectorcnt(27 , 0) , ct(27 , 0);
        for(auto c : s) cnt[c - 'a']++;
        for(auto c : t) ct[c - 'a']++;
        int res = 0;
        for(int i = 0 ; i < 27 ; ++i) res += abs(cnt[i] - ct[i]);
        return res;
    }
};

T3

题目描述:有\(n\)辆公交车不停的跑,第\(i\)辆公交车跑完一圈所需时间为\(time_i\),求所有公交车共跑满\(m\)圈所需要的时间。

思路:比较明显的二分答案,二分最终时间,然后检验这个时间是否能让公交车跑满\(m\)圈即可

时间复杂度:\(O(nlog10^{14})\)

参考代码:

class Solution {
public:
    long long minimumTime(vector& time, int totalTrips) {
        long long lr = 1 , rs = 1e16;
        long long res = 1;
        auto check = [&](long long mid)->bool{
            long long cnt = 0;
            for(auto& t : time){
                cnt += mid / t;
                if(cnt >= totalTrips) return true;
            }
            return false;
        };
        while(lr <= rs){
            long long mid = lr + rs >> 1;
            if(check(mid)) res = mid , rs = mid - 1;
            else lr = mid + 1;
        }
        return res;
    }
};

T4

题目描述:给你一个下标从 0 开始的二维整数数组 tires ,其中 tires[i] = [fi, ri] 表示第 i 种轮胎如果连续使用,第 x 圈需要耗时 \(f_i * r_i^{(x-1)}\) 秒。

  • 比方说,如果 fi = 3ri = 2 ,且一直使用这种类型的同一条轮胎,那么该轮胎完成第 1 圈赛道耗时 3 秒,完成第 2 圈耗时 3 * 2 = 6 秒,完成第 3 圈耗时 3 * 22 = 12 秒,依次类推。

同时给你一个整数 changeTime 和一个整数 numLaps

比赛总共包含 numLaps 圈,你可以选择 任意 一种轮胎开始比赛。每一种轮胎都有 无数条 。每一圈后,你可以选择耗费 changeTime换成 任意一种轮胎(也可以换成当前种类的新轮胎)。

请你返回完成比赛需要耗费的 最少 时间。

思路:考虑到每个轮胎最多连续使用不到\(18\)圈,考虑预处理出每个轮胎连续跑\(j\)圈所需要的总时间数,再求出所有轮胎中连续跑\(j\)圈所花时间的最小值定义为\(min20_j\)。定义状态\(f_i\)表示跑第\(i\)圈所需的时间数,那么转移方程为:

\[f_i = \mathop{min}\limits_{j = i - 18}^{i - 1} f_j + min20_{i- j} + changeTime \]

初始条件:\(f_0 = - changeTime\)

时间复杂度:\(O(20n)\)

参考代码:

class Solution {
public:
    int minimumFinishTime(vector>& tires, int changeTime, int m) {
        int n = tires.size();
        vector>graph(n , vector(20 , 0x3f3f3f3f));
        vector min20(20 , 0x3f3f3f3f);
        for(int i = 0 ; i < n ; ++i){
            int f = tires[i][0] , r = tires[i][1];
            long long p = 1;
            int sum = 0;
            for(int j = 1 ; j < 20 ; ++j){
                long long dx = 1ll * f * p;
                if(dx > graph[i][j]) break;
                graph[i][j] = dx;
                p *= r;
                sum += graph[i][j];
                min20[j] = min(min20[j] , sum);
            }
        }
        vectorf(m + 1 , 0x3f3f3f3f);
        f[0] = - changeTime;
        for(int i = 1 ; i <= m ; ++i){
            for(int j = i - 1 ; j >= max(0 , i - 18) ; --j){
                f[i] = min(f[i] , f[j] + min20[i - j] + changeTime);
            }
        }
        return f[m];
    }
};