Bootstrap

贪心day5

前言

💫你好,我是辰chen,本文旨在准备考研复试或就业
💫文章题目大多来自于 leetcode,当然也可能来自洛谷或其他刷题平台
💫欢迎大家的关注,我的博客主要关注于考研408以及AIoT的内容
🌟 仅给出C++版代码

以下的几个专栏是本人比较满意的专栏(大部分专栏仍在持续更新),欢迎大家的关注:

💥ACM-ICPC算法汇总【基础篇】
💥ACM-ICPC算法汇总【提高篇】
💥AIoT(人工智能+物联网)
💥考研
💥CSP认证考试历年题解

三次操作后最大值与最小值的最小差


题目链接:三次操作后最大值与最小值的最小差

C++版AC代码:

class Solution {
public:
    int minDifference(vector<int>& nums) {
        int n = nums.size();
        if (n < 5) return 0;

        sort(nums.begin(), nums.end());
        int sl[4] = {0};
        for (int i = 0; i < 4; ++ i )
            sl[i] = nums[n + i - 4] - nums[i];
        sort(sl, sl + 4);

        return sl[0];
    }
};

心算挑战


题目链接:心算挑战

C++版AC代码:

class Solution {
public:
    int maximumScore(vector<int>& cards, int cnt) {
        sort(cards.begin(), cards.end(), greater<>());
        
        int res = 0;
        for (int i = 0; i < cnt; ++ i ) 
            res += cards[i];
        
        if (!(res % 2)) return res;

        int sl1res = res, sl2res = res;
        // 找到前cnt中最小的奇数与数组后面最大的偶数交换
        bool flag1[2] = {false, false};    // 前cnt中得存在奇数,剩下的数组存在偶数
        for (int i = cnt - 1; i >= 0; i -- ) 
            if (cards[i] % 2) {
                sl1res -= cards[i];
                flag1[0] = true;
                break;
            }
        if (flag1[0]) {
            for (int i = cnt; i < cards.size(); ++ i ) 
                if (!(cards[i] % 2)) {
                    sl1res += cards[i];
                    flag1[1] = true;
                    break;
                }
        }
        if (!flag1[0] || !flag1[1]) sl1res = 0;

        // 找到前cnt中最小的偶数与数组后面最大的奇数交换
        bool flag2[2] = {false, false};    // 前cnt中得存在偶数
        for (int i = cnt - 1; i >= 0; i -- ) 
            if (!(cards[i] % 2)) {
                sl2res -= cards[i];
                flag2[0] = true;
                break;
            }
        if (flag2[0]) {
            for (int i = cnt; i < cards.size(); ++ i ) 
                if (cards[i] % 2) {
                    sl2res += cards[i];
                    flag2[1] = true;
                    break;
            }
        }
        if (!flag2[0] || !flag2[1]) sl2res = 0;
        
        return max(sl1res, sl2res);
    }
};

可被三整除的最大和


题目链接:可被三整除的最大和

C++版AC代码:

class Solution {
public:
    int maxSumDivThree(vector<int>& nums) {
        sort(nums.begin(), nums.end());

        vector<int> n0, n1, n2;   // 取模分别为0, 1, 2
        int res = 0;
        for (auto x : nums) {
            if (!(x % 3)) n0.push_back(x);
            else if (x % 3 == 1) n1.push_back(x);
            else n2.push_back(x);
            res += x;
        }

        if (!(res % 3)) return res;
        else if (res % 3 == 1) {   // 删除n1中的一个或者删除n2中的两个
            int sl1 = 0, sl2 = 0;
            if (n1.size()) sl1 = res - n1[0];
            if (n2.size() >= 2) sl2 = res - n2[0] - n2[1];
            res = max(sl1, sl2);
        } else {                   // 删除n1中的两个或者删除n2中的一个
            int sl1 = 0, sl2 = 0;
            if (n1.size() >= 2) sl1 = res - n1[0] - n1[1];
            if (n2.size()) sl2 = res - n2[0];
            res = max(sl1, sl2);
        }

        return res;
    }
};

令牌放置


题目链接:令牌放置

C++版AC代码:

class Solution {
public:
    int bagOfTokensScore(vector<int>& tokens, int power) {
        sort(tokens.begin(), tokens.end());

        vector<int> res;
        int cures = 0;
        for (int i = 0, j = tokens.size() - 1; i <= j; ++ i) {
            if (power >= tokens[i]) {
                cures ++;
                res.push_back(cures);
                power -= tokens[i];
            }else if (cures > 0){
                cures --;
                res.push_back(cures);
                power += tokens[j];
                j --, i --;
            }
        }

        if (res.empty()) return 0;
        sort(res.begin(), res.end(), greater<>());

        return res[0];
    }
};

通过最少操作次数使数组的和相等


题目链接:通过最少操作次数使数组的和相等

C++版AC代码:

class Solution {
public:
    int minOperations(vector<int>& nums1, vector<int>& nums2) {
        int len1 = nums1.size(), len2 = nums2.size();
        int maxlen = max(len1, len2), minlen = min(len1, len2);
        // 无解
        if (maxlen > minlen * 6) return -1;
        
        sort(nums1.begin(), nums1.end());
        sort(nums2.begin(), nums2.end());
        int sum1 = accumulate(nums1.begin(), nums1.end(), 0);
        int sum2 = accumulate(nums2.begin(), nums2.end(), 0);

        int t = sum1 - sum2;
        // 无需操作
        if (t == 0) return 0;

        vector<int> l, s;
        if (t >= 0) l = nums1, s = nums2;
        else l = nums2, s = nums1;
        t = max(t, -t);                 // t恒正, 其值代表两个数组的数值差距
        reverse(l.begin(), l.end());    // l从大到小排序, s从小到大排序, 方便操作

        int res = 0, i = 0, j = 0;
        // 根据题意,使两个数组的和相等可以等价为使和较小的数组相等或超过和较大的数组
        while (t > 0) {
            // sl1 代表的是s数组可以变大的极限, sl2 代表的是l数组可以变小的极限
            int sl1 = 0, sl2 = 0;
            if (i < s.size()) sl1 = 6 - s[i];
            if (j < l.size()) sl2 = l[j] - 1;
            
            if (sl1 >= sl2) {
                t -= sl1;
                s[i ++] = 6;
            } else {
                t -= sl2;
                l[j ++] = 1;
            }
            res ++;
        }

        return res;
    }
};
;