LeetCode第 94 场双周赛

1.最多可以摧毁的敌人城堡数目

题目

最多可以摧毁的敌人城堡数目

Solution

可以第一重循环找到\(1\),然后从该位置分别向左和向又寻找\(-1\),寻找过程中遇到\(1\)则停止,不更新ans,遇到\(-1\)则更新ans

class Solution {
public:
    int captureForts(vector<int>& forts) {
        int ans = -1;
        int n = forts.size();
        for(int i = 0;i < forts.size();i++){
            if(forts[i] == 1){
                for(int j = 1;j <= forts.size() - 1 && i + j <= n-1;j++){
                    if(forts[i+j] == 1) break;
                    if(forts[i+j] == -1){
                        ans = max(ans,j);
                        break;
                    }
                }
                for(int j = 1;j <= forts.size()-1 && i - j >= 0 && i != 0; j++){
                    if(forts[i-j] == 1) break;
                    if(forts[i-j] == -1){
                        ans = max(ans,j);
                        break;
                    }
                }
            }
        }
        return ans-1 > 0? ans-1:0;
    }
};

2.奖励最顶尖的 K 名学生

题目

Solution

class Solution {
public:
    vector<int> topStudents(vector<string>& positive_feedback, vector<string>& negative_feedback, vector<string>& report, vector<int>& student_id, int k) {
        unordered_set<string> positive;
        unordered_set<string> negative;
        for(auto &a : positive_feedback){
            positive.insert(a);
        }
        for(auto &a : negative_feedback){
            negative.insert(a);
        }
        unordered_map<int,int> book(student_id.size());
        for(int i = 0;i < report.size();i++){
            stringstream ss;
            string a;
            ss << report[i];//将一句话单词放入
            while(ss>>a){//对每个单词进行检测
                if(positive.find(a) != positive.end()){
                    book[student_id[i]] += 3;
                }else if(negative.find(a) != negative.end()){
                    book[student_id[i]] -= 1;
                }
            }
        }
        sort(student_id.begin(),student_id.end(),[&] (int a, int b){
            if(book[a] < book[b]) return false;
            else if(book[a] > book[b]) return true;
            else return a < b;
        });
        return vector<int>(student_id.begin(),student_id.begin() + k);
    }
};

3.最小化两个数组中的最大值

最小化两个数组中的最大值

Solution

二分答案,每次对二分出来的数进行检测看能否选出题目要求的数的个数,因为每次二分检测的是数的个数,而检测不能被整除的数的个数不如检测能被整除的数的个数容易,所以我们可以先求出能被\(divisor\)整除的数的个数,然后减去这些数,得到不能被整除的数的个数,\(0~k\)之间能被\(divisor\)整除的数的个数我们用\(k / divisor\)可以求得。

注意,check和lcm要用long long,不然会WA。

class Solution {
public:
    int minimizeSet(int divisor1, int divisor2, int uniqueCnt1, int uniqueCnt2) {
        int l = uniqueCnt1 + uniqueCnt2,r = INT_MAX;
        auto check = [&](long long k,long long d1,long long d2,long long c1,long long c2){
            //c11代表0~k中有多少个数能被d1整除,c22代表0~k中有多少个数能被d2整除,c12是多少个数能被d1和d2整除
            long long c11 = k / d1, c22 = k / d2, c12 = k / (lcm(d1,d2));
            c11 = c11 - c12;//现在表示能被放入arr2中数的个数
            c22 = c22 - c12;//现在表示能被放入arr1中数的个数
            k = k - c12;//现在表示有多少个数可以被选择
            if(c11 > c2){
                k -= (c11 - c2);
            }
            if(c22 > c1){
                k -= (c22 - c1);
            }
            return k >= (c1+c2);
        };
        auto lcm = [&](long long a,long long b){
            return a * b / gcd(a,b);
        };
        while(l < r){
            int mid = l + (r - l) / 2;
            //cout<<"l:"<<l<<" "<<"r:"<<r<<endl;
            if(check(mid,divisor1,divisor2,uniqueCnt1,uniqueCnt2)){
                r = mid;
            }else{
                l = mid+1;
            }
        }
        return l;
    }
private:
    int gcd(int a, int b) {
        while(b){
            int t = a;
            a = b;
            b = t % b;
        }
        return a;
    }
};

4. 统计同位异构字符串数目

统计同位异构字符串数目

Solution

对每个单词求全排列在将各自的全排列乘起来,这道题困难就困难在求全排列,全排列的阶乘可能会很大,所以要用逆元求解。

class Solution {
    long long mod = 1e9+7;
    long solve(string &s){//计算全排列

        unordered_map<int,int> memo;//用来存放质因数出现的次数
        vector<int> cnt(26);//存放每个字母出现的次数
        for(char &c:s)
            ++cnt[c-'a'];
        for(int num=2;num<=s.size();++num)//对分子——元素个数的阶乘作质因数分解
        {
            int n=num;
            for(int i = 2; i <= sqrt(n); i ++)
                if(n % i == 0)
                    while(n % i == 0)
                    {
                        ++memo[i];
                        n /= i;
                    }
            if(n != 1) 
                ++memo[n];
        }
        for(int k:cnt)
            for(int num=2;num<=k;++num)//对每个重复次数的阶乘作质因数分解,并从memo中减掉
            {
                int n=num;
                for(int i = 2; i <= sqrt(n); i ++)
                    if(n % i == 0)
                        while(n % i == 0)
                        {
                            --memo[i];
                            n /= i;
                        }
                if(n != 1) 
                    --memo[n];
            }
        long ans=1;
        for(auto &p:memo)//对分子剩下的质因数作乘法
            while(p.second)
                ans=(ans*p.first)%mod,--p.second;
        return ans;
    }
public:
    int countAnagrams(string s) {
        long long ans = 1;
        stringstream ss(s);
        string str;
        while(ss >> str){
            ans = (ans*solve(str)) % mod;
        }
        return ans;
    }
};
posted @ 2022-12-31 19:39  TTS-S  阅读(21)  评论(0编辑  收藏  举报