当前位置:网站首页>Leetcode 周赛 218 题解

Leetcode 周赛 218 题解

2020-12-07 21:46:30 DWVictor

5617. 设计 Goal 解析器

按题意模拟,基础题。

class Solution {
public:
    string str;
    string interpret(string command) {
        for(int i = 0; i < command.size();i++){
            if(command[i] == 'G') str += 'G';
            else if(i != command.size() - 1 && command[i] == '(' && command[i + 1] == ')') str += 'o';
            else if(command[i] == 'a') str += "al";
        }
        return str;
    }
};

5618. K 和数对的最大数目

经典技巧题,比较好的解法是排序之后双指针求解。当然可以用map投机就很好写了。

双指针求解

class Solution {
public:
  int maxOperations(vector<int>& nums, int k) {
    int N =  nums.size();
    sort(nums.begin(), nums.end());
    int ans = 0;
    int l = 0, r = nums.size() - 1;
    while (l<r) {
      int s = nums[l]+nums[r];
      if (s == k) l++, r--, ans++;
      else if (s < k) l++;
      else r--;
    }
    return ans;
  }
};

map

class Solution {
public:
    int maxOperations(vector<int>& nums, int k) {
        map<int, int> mp;
        int ans = 0;
        for(int x: nums) {
            if(mp[k - x] > 0) {
                mp[k - x] -= 1;
                ++ ans;
            }else mp[x] += 1;
        }
        return ans;
    }
};

5620. 连接连续二进制数字

从后往前求每个数的贡献值即可

class Solution {
public:
    int concatenatedBinary(int n) {
        long long mod = pow(10,9) + 7;
        long long ans = 0, base = 1;
        for(int i = n; i >= 1; --i) {
            n = i;
            while(n > 0) {
                long long x = n & 1;
                n >>= 1;
                ans = (ans + base * x) % mod;
                base = base * 2 % mod;
            }
        }
        return (int)ans;
    }
};

5619. 最小不兼容性

数组和权值范围最大只有16,因为要把数组分成k个子集,那么每个子集大小就是n/k。

第一种方法:

通过set判断子集中的重复元素,搜索+剪枝即可,具体见代码

class Solution {
public:
    int N;//总个数
    int K;//子集个数
    int M;//每个子集中的元素个数
    int ans;//求解值
    void dfs(vector<int>& nums,int index,vector<set<int>> &vSet,int have){
    	/*
    	index 表示当前数组取到的值
    	vSet 表示子集
    	*/
        if(index>=N){//当取到最后一位时终止,判断
            ans=min(ans,have);
            return;
        }
        
        for(int i=0;i<K;i++){
            if(vSet[i].empty()){// 子集个数为空
                vSet[i].insert(nums[index]);
                dfs(nums,index+1,vSet,have);//取下个元素
                vSet[i].erase(nums[index]);
                break;//当有出现大于K个相同数时,不可能
            }
            if(vSet[i].size()<M&&vSet[i].find(nums[index])==vSet[i].end()){//当前子集个数未满且当前元素子集中未存在
                if(have + nums[index] - *vSet[i].rbegin()>=ans){
                	//剪枝 当前数已经比最小值大
                    continue;
                }
                int nhave = have + nums[index] - *vSet[i].rbegin();
                vSet[i].insert(nums[index]);
                dfs(nums,index+1,vSet,nhave);

                vSet[i].erase(nums[index]);                
            }
        }
        
    }
    int minimumIncompatibility(vector<int>& nums, int k) {
        N=nums.size();
        sort(nums.begin(),nums.end());
        ans = INT_MAX;
        K=k;
        M=N/K;
        vector<set<int>> vSet(k);
        dfs(nums,0,vSet,0);
        if(ans == INT_MAX){
            return -1;
        }
        return ans;
    }
};

第二种方法:

首先二进制枚举求出所有合法的子集,这样的子集个数不会太多。

可以通过二进制枚举求出所以合法的子集,同状态压缩。

然后写一个搜索+剪枝即可。

class Solution {
public:
    int ans, n, sz;
    vector<pii> vs;
    void dfs(int c, int cnt, int sta, int res, int k) {
        if(cnt == k) {
            ans = min(ans, res);
            return ;
        }
        if(res >= ans) return ;
        for(int i = c; i < sz; ++i) {
            if((sta & vs[i].se) == 0) dfs(i + 1, cnt + 1, sta | vs[i].se, res + vs[i].fi, k);
        }
    }
    int minimumIncompatibility(vector<int>& nums, int k) {
        vector<int> cnt(20, 0);
        int flag = 1;
        ans = INF;
        for(int x: nums) {
            ++ cnt[x];
            if(cnt[x] > k) flag = 0;
        }
        if(flag == 0) return -1;
        n = nums.size();
        int sta = 1 << n;
        sort(all(nums));
        for(int i = 1; i < sta; ++i) {
            int cnt = 0, Mx = 0, Mn = 100, las = -1;
            for(int j = 0; j < n; ++j) {
                if(i & (1 << j)) {
                    ++ cnt;
                    Mx = max(Mx, nums[j]);
                    Mn = min(Mn, nums[j]);
                    if(nums[j] == las) cnt = -100;
                    las = nums[j];
                }
            }
            if(cnt * k == n) {
                vs.emplace_back(make_pair(Mx - Mn, i));
            }
        }
        sort(all(vs));
        sz = vs.size();
        dfs(0, 0, 0, 0, k);
        vs.clear();
        return ans;
    }
};

版权声明
本文为[DWVictor]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/DWVictor/p/14099736.html