Leetcode 力扣周赛 182

143 阅读3分钟

5368. 找出数组中的幸运数

首先遍历数组 nums,统计每个数出现的次数,存储在数组 cnt 中,cnt[i] 即为 数字 i 出现的次数。遍历 cnt ,寻找满足 cnt[i] == i 的最大 的 i。

class Solution {
public:
    int findLucky(vector<int>& arr) {
        int cnt[501] = {0};
        for(auto v : arr) {
            cnt[v]++;
        }
        int anw = -1;
        for(int i = 1; i <= 500; i++) {
            if(cnt[i] == i) {
                anw = i;
            }
        }
        return anw;
    }
};

5369. 统计作战单位数

首先遍历数组rating,从0开始枚举下标 i ,统计满足 rating[j] < rating[i] 或者 rating[j] > rating[i] ,且 j < i 的 j 的个数。分别存储在lt[i] 和 gt[i] 中。时间复杂度 O(n^2)。 然后遍历 lt 和 gt,从 0 开始枚举下标 i,累加满足 **rating[j] < rating[i] 且 j < i ** 的 lt[j],累加满足 rating[j] > rating[i] 且 j < i 的 gt[j]。

class Solution {
public:
    int numTeams(vector<int>& rating) {
        int cnt[2][200] = {0};
        for(int i = 1; i < rating.size(); i++) {
            for(int j = 0; j < i; j++) {
                if(rating[j] < rating[i]) {
                    cnt[0][i]++;
                } else if(rating[j] > rating[i]) {
                    cnt[1][i]++;
                }
            }
        }
        int anw = 0;
        for(int i = 1; i < rating.size(); i++) {
            for(int j = 0; j < i; j++) {
                if(rating[j] < rating[i]) {
                    anw += cnt[0][j];
                } else if(rating[j] > rating[i]) {
                    anw += cnt[1][j];
                }
            }
        }
        return anw;
    }
};

5370. 设计地铁系统

可以使用 STL 来存储数据,高效实现地铁管理系统🐶。 数据容器的设计可以参见注释。

class UndergroundSystem {
public:
    UndergroundSystem() {
        
    }
    //所有完成的通行记录
    //key.first 为上车站,key.second 为下车站
    //value.first 为累计用时,value.second 为完成的通行次数。
    map<pair<string, string>, pair<int64_t, int>> data;
    //缓存乘客尚未完成的通行记录
    //key 为 乘客ID
    //value.first 为乘客上车站,value.second 为出发时间。
    //乘车下车后,记录应从该容器中移除。
    map<int, pair<string, int>> passenger;
    void checkIn(int id, string stationName, int t) {
        passenger[id] = make_pair(stationName, t);
    }
    
    void checkOut(int id, string stationName, int t) {
        auto it = passenger.find(id);
        data[make_pair(it->second.first, stationName)].first += t - it->second.second;
        data[make_pair(it->second.first, stationName)].second ++;
        passenger.erase(it);
    }
    
    double getAverageTime(string startStation, string endStation) {
        auto it = data.find(make_pair(startStation, endStation));
        return double(it->second.first)/(it->second.second);
    }
};

5371. 找到所有好字符串

可以使用动态规划 + 容斥原理来解决该题。 首先处理特殊数据,如果 s1 > s2 ,直接返回 0 。

然后用容斥原理简化一下问题: 设函数 f(s, evil) 可以计算出字典序不超过 s 且不包含 evil 的字符串的数量。另设置一个变量 cnt,当 s1 包含 evil时, cnt = 0, 否则 cnt = 1。那么最终答案为 f(s2, evil) - f(s1, evil) + cnt。 设置 cnt 的目的是:当 f(s1, evil) 返回的数量中包含 s1 本身时,需要避免 s1 被容斥排除掉。

用动态规划来实现 f(s, evil)。动态规划数组dp[i][j][k]。第一维度表示拼接过程中,当前字符串的长度,第二维度表示拼接过程中,当前字符串是否与 s 的等长前缀相同。 j = 1 表示相同,j = 0 表示不相同。第三维度表示当前字符串的后缀与 evil 的前缀的重叠长度。 当 i = 0时,显然有 dp[0][1][0] = 1,对于其他 dp[0][x][y] 均为 0。 接下来枚举下一个拼接的字符 c ,根据题意计算出从当前状态 dp[i][j][k] 后拼接 c 后转移到 ni,nj,nk。状态转移策略参考代码注释。 f(s, evil)的返回结果记为 dp[n][0][m],dp[n][1][m]的累加和,m∈[0,evil.size()]。

const int64_t MOD = 1000000007;
inline void add(int64_t &a, int64_t b) {
    a += b;
    if(a >= MOD) {
        a %= MOD;
    }
}
class Solution {
public:
    void get(const string &s, const string &evil, int n, int64_t &sum, int64_t &part) {
        int64_t dp[501][2][51] = {0};
        int m = evil.size();
        dp[0][1][0] = 1;
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < 2; j++) {
                for(int k = 0; k < m; k++) {
                    for(char c = 'a'; c <= 'z'; c++) {
                        int ni = i+1, nj = -1, nk = -1;
                        if(j == 1) {
                            if(c > s[i]) {
                                //当前字符串与s前缀相同,
                                // 所以不能拼接更大的 c。
                                break;
                            }
                            if(c == s[i]) {
                                //拼接完后仍与s前缀相同,
                                //所以 nj = 1。
                                nj = 1;
                            } else { 
                                //拼接完后小于s前缀,
                                //所以 nj = 0。
                                nj = 0;
                            }
                        } else {
                            //已经比s前缀小了,
                            //无论拼接什么字符,仍然是小。
                            nj = 0;
                        }
                        if(c == evil[k]) {
                            //已经重叠了k个字符,
                            //且 c 与 evil的第k+1字符相等,
                            //所以 nk = k+1
                            nk = k+1;
                        } else {
                            //尝试寻找最大的与evil的重叠长度
                            nk = 0;
                            for(int p = 0; p <= k; p++) {
                                int len = (k-p);
                                if(evil[len] != c) { continue; }
                                bool flag = true;
                                for(int q = 0; q < len; q++) {
                                    if(evil[q] != evil[q+p]) { flag = false; break; }
                                }
                                if(flag) { nk = len+1; break;}
                            }
                        }
                        //nk == m 时,说明当前字符串已经包含了 evil
                        //所以不能记入总数。
                        if(nk == m) {
                            continue;
                        }
                        add(dp[ni][nj][nk], dp[i][j][k]);
                    }
                }
            }
        }
		sum = 0, part = 0;
        for(int i = 0; i < m; i++) {
            add(sum, dp[n][0][i]);
            add(sum, dp[n][1][i]);
            add(part, dp[n][1][i]);
        }
    }
    int findGoodStrings(int n, string s1, string s2, string evil) {
        if (s1 > s2) {
            return 0;
        }
        int64_t sum1, part1;
        int64_t sum2, part2;
        get(s1, evil, n, sum1, part1);
        get(s2, evil, n, sum2, part2);
        return (sum2+part1-sum1+MOD)%MOD;
    }
};