每日一练 | Day 1

LCP 40. 心算挑战

题目链接

https://leetcode.cn/problems/uOAnQW/

相关算法

贪心、排序

题目描述

「力扣挑战赛」心算项目的挑战比赛中,要求选手从 N 张卡牌中选出 cnt 张卡牌,若这 cnt 张卡牌数字总和为偶数,则选手成绩「有效」且得分为 cnt 张卡牌数字总和。 给定数组 cardscnt,其中 cards[i] 表示第 i 张卡牌上的数字。 请帮参赛选手计算最大的有效得分。若不存在获取有效得分的卡牌方案,则返回 0

  • 数据范围:
    1 <= cnt <= cards.length <= 10^5
    1 <= cards[i] <= 1000

解题思路

本题显然可以用贪心的思路,无论是否满足条件,先尽可能将最大的卡牌加到结果中,然后如果不满足总和为偶数的情况,再进行调整。因此,优先将数组进行排序,并求出前 cnt 大的卡牌数字总和。

 Arrays.sort(cards);
 int sum = 0;
 for (int i = cards.length - 1; i >= cards.length - cnt; i--) {
    sum += cards[i];
}

然后,如果结果为偶数,就可以直接进行返回,而如果结果为奇数,则需要进行处理:将结果中的一个偶数移除,替换成一个奇数,或者移除一个奇数,换上一个偶数。根据贪心算法,我们移除的数应该尽可能小,换上的数应该尽可能大。
首先,我们调整一下前面的部分,在计算和的时候,同时把结果中最小的奇数和偶数记录下来,此处分别使用变量 min0min1 存储结果中最小的偶数和奇数

int min0 = Integer.MAX_VALUE, min1 = Integer.MAX_VALUE;
for (int i = cards.length - 1; i >= cards.length - cnt; i--) {
    sum += cards[i];
    if (cards[i] % 2 == 0) {
        min0 = Math.min(min0, cards[i]);
    } else {
        min1 = Math.min(min1, cards[i]);
    }
}

接下来,统计数组剩余部分中最大的奇数和偶数,此处分别使用变量 max0max1 存储

int max0 = Integer.MIN_VALUE, max1 = Integer.MIN_VALUE;
for (int i = cards.length - cnt - 1; i >= 0; i--) {
    if (max0 != Integer.MIN_VALUE && max1 != Integer.MIN_VALUE) {
        break;
    }
    if (cards[i] % 2 == 0) {
        max0 = Math.max(max0, cards[i]);
    } else {
        max1 = Math.max(max1, cards[i]);
    }
}

最后就是进行替换操作,将两种情况中的最大值返回。但是此处有陷阱:可能存在min0min1max0max1 表示的值不存在的情况,即中间遍历的部分数组是纯奇数或纯偶数,因此要进行详细的判断

int result = Integer.MIN_VALUE;
if (min0 != Integer.MAX_VALUE && max1 != Integer.MIN_VALUE) {
    result = Math.max(result, sum - min0 + max1);
}
if (min1 != Integer.MAX_VALUE && max0 != Integer.MIN_VALUE) {
    result = Math.max(result, sum - min1 + max0);
}
return result == Integer.MIN_VALUE ? 0 : result;

至此,题目完成

完整代码

class Solution {
    public int maxmiumScore(int[] cards, int cnt) {
        Arrays.sort(cards);
        int sum = 0;
        int min0 = Integer.MAX_VALUE, min1 = Integer.MAX_VALUE;
        for (int i = cards.length - 1; i >= cards.length - cnt; i--) {
            sum += cards[i];
            if (cards[i] % 2 == 0) {
                min0 = Math.min(min0, cards[i]);
            } else {
                min1 = Math.min(min1, cards[i]);
            }
        }
        if (sum % 2 == 0) {
            return sum;
        }
        int max0 = Integer.MIN_VALUE, max1 = Integer.MIN_VALUE;
        for (int i = cards.length - cnt - 1; i >= 0; i--) {
            if (max0 != Integer.MIN_VALUE && max1 != Integer.MIN_VALUE) {
                break;
            }
            if (cards[i] % 2 == 0) {
                max0 = Math.max(max0, cards[i]);
            } else {
                max1 = Math.max(max1, cards[i]);
            }
        }
        int result = Integer.MIN_VALUE;
        if (min0 != Integer.MAX_VALUE && max1 != Integer.MIN_VALUE) {
            result = Math.max(result, sum - min0 + max1);
        }
        if (min1 != Integer.MAX_VALUE && max0 != Integer.MIN_VALUE) {
            result = Math.max(result, sum - min1 + max0);
        }
        return result == Integer.MIN_VALUE ? 0 : result;
    }
}
  • 时间复杂度:O(nlogn)
  • 空间复杂度:O(1)
  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值