leetcode 第222场周赛 题解

卡车上的最大单元数
思路:贪心
按照能装载的单元数量从大到小排直接选即可

class Solution {
public:
    int maximumUnits(vector<vector<int>>& b, int t) {
            sort(b.begin(),b.end(),[](vector<int> a,vector<int> b){
                return a[1]>b[1];
            });
            int ans=0;
            for(auto &x:b){
                if(t>=x[0]){
                    t-=x[0];
                    ans+=x[0]*x[1];
                }
                else {
                    ans+=x[1]*t;
                    break;
                }
            }
            return ans;
    }
};

大餐计数
思路:哈希
开个map记录前面的数字,注意到范围,所以暴力枚举1、2、4…2^21
一边计算一边取模即可

const int mod=1e9+7;
typedef long long ll;
class Solution {
public:
    int mp[1<<22];
    int countPairs(vector<int>& d) {
        ll ans=0;
        for(auto &x:d){
            for(int i=0;i<=21;i++){
                if((1<<i)>=x)ans+=mp[(1<<i)-x];
                if(ans>=mod) ans-=mod;
            }
            mp[x]++;
        }
        return ans;
    }
};

将数组分成三个子数组的方案数
思路:将序列分成了三部分,那么就是有两个分界线,将序列分成了三部分,所以我们枚举第一个区间left的右边界,然后二分出来二倍left的区间和,计算出来第二个区间的右端点的最小位置pos1。然后我们去计算第二个区间右端点的最远位置pos2就好了,贡献就是pos2-pos1+1

注意:区间要求非空,所以
pos1=max(pos1,i+1)
pos2=min(pos2,n-1)
当时因为这个wa了两发。。
可以先前缀和求一下 方便求区间的和

typedef long long ll;
const ll mod=1e9+7;
class Solution {
public:
    ll s[1<<20];
    int waysToSplit(vector<int>& nums) {
        int n=nums.size();
        for(int i=1;i<=n;i++){
            s[i]=s[i-1]+nums[i-1];//前缀和
        }
        ll ans=0;
        for(int i=1;i<=n;i++){
            int pos1=lower_bound(s+1,s+n+1,2*s[i])-s;
            pos1=max(pos1,i+1);//第二个区间的满足要求的第一个右端点pos1
            if(pos1<n){
                ll sum=s[n]-s[i];
                int pos2=upper_bound(s+1,s+n+1,s[i]+sum/2)-s;
                pos2--;//使得第二个区间小于等于第三个区间和
                pos2=min(pos2,n-1);//注意第三个区间非空 所以右端点最多到n-1
                if(pos2>=pos1){
                    ans+=pos2-pos1+1;
                    ans%=mod;
                }
            }
        }
        return ans;
    }
};

得到子序列的最少操作次数
思路:很容易知道直接求最长公共子序列即可,但是数据范围不允许n^2的时间复杂度
所以考虑别的做法。容易发现arr数组中在target中不存在的元素是没用的。
注意到target中的元素互不相同。
所以我们对target按顺序进行1 2 3 …n进行编号
然后对在arr数组中在target的元素求一下最长上升子序列就好了。

map<int,int>mp;
class Solution {
public:
    int minOperations(vector<int>& t, vector<int>& a) {
        mp.clear();
        for(int i=0;i<t.size();i++){
            mp[t[i]]=i+1;
        }
        vector<int> b;
        for(auto &x:a){
            if(!mp[x]) continue;
            if(b.size()){
                if(mp[x]>b[b.size()-1]) b.push_back(mp[x]);
                else{
                    int pos=lower_bound(b.begin(),b.end(),mp[x])-b.begin();
                    b[pos]=mp[x];
                }
            }
            else b.push_back(mp[x]);
        }
        return t.size()-b.size();
    }
};

你可能感兴趣的:(leetcode题解)