Leetcode 第 338 场周赛 题解


title: 第 338 场周赛
date: 2023-03-29 16:31:08
categories: Leetcode周赛
mathjax: true


第 338 场周赛

K 件物品的最大和

贪心,直接按照1,0,-1选即可

class Solution {
public:
    int kItemsWithMaximumSum(int numOnes, int numZeros, int numNegOnes, int k) {
        int res = 0;
        if(k<=numOnes) return k;
        else if(numOnes+numZeros>=k) return numOnes;
        else return numOnes - (k - numOnes - numZeros);
    }
};

质数减法运算

先筛出1000以内的质数,因为数值范围比较小,怎么筛都行。因为题目要求严格递减,根据贪心思想,我们让每个数在满足递增的条件下尽可能的小。

class Solution {
    
    
public:
    bool primeSubOperation(vector<int>& nums) {
    
    
        vector<int>p;
        for(int i=2;i<=1010;++i)
        {
    
    
            int st = 1;
            for(int j =2;j*j<=i;++j)
                if(i%j == 0) st = 0;
            if(st == 1) p.push_back(i);
        }
        int lst = 0;
        for(int i = 0;i<nums.size();++i)
        {
    
    
            int st = 0;
            for(int j = p.size()-1;j>=0;j--)
            {
    
    
                if(p[j]< nums[i] && nums[i] - p[j] > lst)
                {
    
    
                    lst = nums[i] - p[j];
                    st = 1;
                    break;
                }
            }
            if(st == 0)
            {
    
    
                if(nums[i] > lst) lst = nums[i];
                else return false;
            }
        }
        return true;
    }
};

使数组元素全部相等的最少操作次数

对整数数组排序,若当前要变成x,在排序数组内找到第一个大于等于x的数,这个数的下标记为j,则要变换的次数为: t ∗ x − s u m [ j − 1 ] + s u m [ N ] − s u m [ j − 1 ] − ( N − j + 1 ) ∗ x t *x - sum[j-1] + sum[N] - sum[j-1] - (N - j + 1) * x txsum[j1]+sum[N]sum[j1](Nj+1)x

实现的时候注意边界判断。

#include <algorithm>
class Solution {
    
    
public:
    vector<long long> minOperations(vector<int>& num, vector<int>& queries) {
    
    
        vector<int>nums = num;
        sort(nums.begin(),nums.end());
        vector<long long>sum(1000010,0);
        for(int i=0;i<nums.size();++i)
            if(i == 0)sum[i] =nums[i];
            else sum[i] =sum[i-1]+nums[i];   
        vector<long long>ans;
        for(int i=0;i<queries.size();++i)
        {
    
    
            if(nums.size()==1) ans.push_back(abs(queries[i] - nums[0]));
            else 
            {
    
    
                long long t = lower_bound(nums.begin(),nums.end(),queries[i])-nums.begin();

                long long x =0 ,y = 0;
                if(t > 0) x = t * queries[i] - sum[t-1];
                if(t == 0) y = sum[nums.size()-1] - (nums.size() - t) * queries[i];
                else if(t <= nums.size()-1) y = sum[nums.size()-1] - sum[t-1] - (nums.size() - t) * queries[i];
                ans.push_back(x + y);
            }
        }
        return ans;
    }
};

收集树中金币

不难发现:

  • 对于没有金币的叶子(树枝)节点对最终的答案是没有影响的。
  • 将所有没有金币的叶子(树枝)删出后,得到一颗新的树,此时不管从哪个节点开始收集,最后的答案的都是一样的

根据上述结论,可以用拓扑排序删去多余的树枝,删除后再跑一遍拓扑排序得到最后的答案。

class Solution {
    
public:
    int collectTheCoins(vector<int>& coins, vector<vector<int>>& edges) {

        const int N = coins.size(),M = edges.size()*2;
        vector<int>e(M, 0),h(N, -1),ne(M, 0);
        vector<int>d(N, 0),dist(N, 0),st(N, 1);

        int idx = 0;
        function<void(int, int)> add = [&](int a, int b)
        {
            e[idx] = b;
            ne[idx] = h[a];
            h[a] = idx ++;
        };

        for(auto p: edges)
        {
            int a = p[0], b = p[1];
            add(a, b), add(b, a);
            d[a] ++, d[b] ++;
        }

        int n = coins.size();
        queue<int>q;
        for(int i = 0; i < n; i ++ )
            if(d[i] == 1 && coins[i] == 0) q.push(i);

        while(!q.empty())
        {
            int p = q.front();
            q.pop();
            st[p] = 0;
            for(int i = h[p]; i!=-1;i=ne[i])
            {
                int j =e[i];
                if(--d[j] == 1 && coins[j] == 0) q.push(j);
            }
        }


        for(int i = 0; i < n; ++ i) d[i] = 0;

        for(auto p: edges)
        {
            int a = p[0], b = p[1];
            if(st[a] == 0 || st[b] == 0) continue;
            d[a] ++, d[b] ++;
        }

        while(!q.empty()) q.pop();

        for(int i=0;i<n;++i)
            if(d[i] == 1 && st[i] == 1)
            {
                q.push(i);
                dist[i] = 0;
            }
        
        int mx = -1,mxid = -1;
        while(!q.empty())
        {
            auto p = q.front();
            q.pop();
        
            for(int i = h[p];i!=-1;i=ne[i])
            {
                int j = e[i];
                d[j] --;
                if(d[j] == 1) 
                {
                    q.push(j);
                    dist[j] = dist[p] + 1;
                }
                
                if(dist[j] >= mx) mx = dist[j], mxid = j;
            }
        }
        int cnt = 0;  
        function<void(int, int)> dfs = [&](int u, int fa)
        {
            for(int i = h[u];i!=-1;i=ne[i])
            {
                int j = e[i];
                if(j == fa) continue;
                if(st[j] == 0) continue;
                if(dist[j] < 2) continue;
                cnt ++;
                dfs(j ,u);
            }
        };
        if(mxid == -1) return 0;
        dfs(mxid, -1);
        return cnt * 2;
    }
};

猜你喜欢

转载自blog.csdn.net/wenyisir/article/details/129840366
今日推荐