Leetcode双周赛74

将数组划分成相等数对

thinking

哈希表统计数字次数即可

solution

class Solution {
public:
    bool divideArray(vector<int>& nums) {
        unordered_map<int,int> hash;
        for(int &val:nums) {
            ++hash[val];
        }
        for(auto &[index,cnt]:hash) {
            if(cnt%2==1) return false;
        }
        return true;
    }
};

字符串中最多数目的子字符串

thinking

贪心,我们考虑从到加入的那个字符在哪,对于加入的那个字符来说,我们用a,b来表示给定的模式串,那么插入的字符必定是a,b中字符最小的那个,且将这个字符插在所有的另一个字符的前面或者后面(为简化,我们直接将字符串插在开头或者结尾)。

剩下再统计原来的字符串中出现模式串的个数加上最大a,b的长度即可。

注意:采用下标进行存a,b的位置时,进行计算时,判断两者的下个位置,这个步骤需要用二分进行操作,不然会TLE

solution

class Solution {
public:
    long long maximumSubsequenceCount(string t, string p) {
        vector<int> a,b;
        int n=t.size();
        for(int i=0;i<n;++i) {
            if(t[i]==p[0]) a.push_back(i);
            if(t[i]==p[1]) b.push_back(i);
        }
        long long ans=0;
        int n1=a.size(),n2=b.size();
        for(int i=0;i<n1;++i) {
            int cnt=upper_bound(b.begin(),b.end(),a[i])-b.begin();
            ans+=n2-cnt;
        }
        return ans+max(n1,n2);
    }
};

将数组和减半的最少操作次数

thinking

大根堆模拟

solution

class Solution {
public:
    int halveArray(vector<int>& nums) {
        priority_queue<double> q;
        double sum=0;
        for(auto &x:nums) {
            sum+=x;
            q.push(x);
        }
        double stay=sum/2.0;
        int cnt=0;
        while(sum>stay) {
            auto num=q.top();
            q.pop();
            sum-=num/2.0;
            q.push(num/2.0);
            ++cnt;
        }
        return cnt;
    }
};

用地毯覆盖后的最少白色砖块

thinking

来自灵神的智商碾压(link),赛时,我01背包找方案没写出来,换成dfs也没写对。。。。

可以简单地说明贪心是错误的,这一点我在赛时也避开了这一问题。下面我们来按照灵神的思路进行dp操作:

定义\(dp[i][j]\)表示用第i个地毯,覆盖前j块板砖的时候,没被覆盖的白色砖块的最小数目

因此,我们考虑是否用第i条地毯的末尾覆盖第j块地板,我们有状态转移方程:

\[1、不覆盖\\f[i][j]=f[i][j-1]+[floor[j]=='1']\\ 2、覆盖\\f[i][j]=f[i-1][j-carpetlen] \]

solution

class Solution {
public:
    int minimumWhiteTiles(string &floor, int n, int carpetLen) {
        int m = floor.size();
        vector<vector<int>> f(n + 1, vector<int>(m));
        f[0][0] = floor[0] % 2;
        for (int i = 1; i < m; ++i)
            f[0][i] = f[0][i - 1] + floor[i] % 2;
        for (int i = 1; i <= n; ++i)
            // j < carpetLen 的 f[i][j] 均为 0
            for (int j = carpetLen; j < m; ++j)
                f[i][j] = min(f[i][j - 1] + floor[j] % 2, f[i - 1][j - carpetLen]);
        return f[n][m - 1];
    }
};
posted @ 2022-03-21 19:49  圣道  阅读(23)  评论(0)    收藏  举报