力扣 LCP 40. 心算挑战

Tips:

LCP“力扣杯”的题目,难度比正常题库题高一个级别,这道题算是中等题。

题目:

题目解读:

题目意思简单,就是在n张卡牌中找cnt张卡牌的数值总和最大值,且该最大值为偶数。

思路:

1.

第一眼看到这道题就想暴力枚举来解决,但是看到提示:1 <= cnt <= cards.length <= 10^5

可知数据量达到10的5次方,可知暴力枚举不可行。

2.

我按照我们老师提供的思路以及我根据这个思路写的c++代码进行思路解析:

首先将数组排序,取最大的cnt个求和,如果为偶数,则可以直接返回。如果为奇数的话则先找出已选卡牌的最小奇数牌和最小偶数牌(存在的话),再找出未选卡牌的最大奇数牌和最大偶数牌(存在的话)。之后就可以进行替换了,找到最小偶数(已选)的话就替换最大奇数(未选),找到最小奇数(已选)的话就替换最大偶数(未选)。替换之后更新他们的和,然后返回更新后的和即可。

这里我对我们老师的思路进行了一个通俗化的讲解,接下来展示代码。

代码:

class Solution {
public:
    int maximumScore(vector<int>& cards, int cnt) {
        //排序
        sort(cards.begin(),cards.end());
        // 取最大的 cnt 个数进行求和
        int sum=0;
        for(int i=cards.size()-cnt;i<cards.size();i++)
        {
            sum+=cards[i];
        }
        //如果和是偶数,直接返回
        if (sum%2==0)
        {
            return sum;
        }
        //如果不是则进行以下操作
        int minOddSelected = INT_MAX, minEvenSelected = INT_MAX;//已选卡牌的最小奇数和最小偶数
        int maxOddUnselected = INT_MIN, maxEvenUnselected = INT_MIN;//未选卡牌的最大奇数和最大偶数
        //遍历已选的 cnt 个卡牌
        for(int i=cards.size()-cnt;i<cards.size();i++)
        {
            if (cards[i]%2==0)
            {
                minEvenSelected = min(minEvenSelected, cards[i]);
            } 
            else 
            {
                minOddSelected = min(minOddSelected, cards[i]);
            }
        }
        //遍历未选的卡牌
        for (int i=0;i<cards.size()-cnt;i++)
        {
            if (cards[i]%2==0) 
            {
                maxEvenUnselected = max(maxEvenUnselected, cards[i]);
            } 
            else 
            {
                maxOddUnselected = max(maxOddUnselected, cards[i]);
            }
        }
        //初始化 bestSum 为 0
        int bestSum = 0;
        // 替换方案1: 替换最小偶数 (已选) 为 最大奇数 (未选)
        if (minEvenSelected != INT_MAX && maxOddUnselected != INT_MIN)
        {
            int newSum = sum - minEvenSelected + maxOddUnselected;
            if (newSum % 2 == 0)
            {
                bestSum = max(bestSum, newSum);
            }
        }
        // 替换方案2: 替换最小奇数 (已选) 为 最大偶数 (未选)
        if (minOddSelected != INT_MAX && maxEvenUnselected != INT_MIN)
        {
            int newSum = sum - minOddSelected + maxEvenUnselected;
            if (newSum % 2 == 0)
            {
             bestSum = max(bestSum, newSum);
            }
        }
        return bestSum;
    }
};

代码按照思路写的比较通俗易懂了。

注:

初始化bestsum为0那里,一开始写的初始化bestsum为sum,但是只通过了一部分用例。

如果我们初始化bestsum为sum,那么如果原始的sum不是偶数,我们会错误地将其作为潜在的最佳和,这会导致错误的结果。

初始化bestsum为0是一种更安全的方法,因为这样1.可以确保我们始终能找到一个有效的偶数和,即使所有可能的替换操作都没有提供更大的偶数和。2.可以确保在没有任何有效的偶数和时,bestsum也不会比实际找到的和更小。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值