心算挑战
原题
「力扣挑战赛」心算项目的挑战比赛中,要求选手从 N 张卡牌中选出 cnt 张卡牌,若这 cnt 张卡牌数字总和为偶数,则选手成绩「有效」且得分为 cnt 张卡牌数字总和。 给定数组 cards 和 cnt,其中 cards[i] 表示第 i 张卡牌上的数字。 请帮参赛选手计算最大的有效得分。若不存在获取有效得分的卡牌方案,则返回 0。
示例 1:
输入:cards = [1,2,8,9], cnt = 3
输出:18
解释:选择数字为 1、8、9 的这三张卡牌,此时可获得最大的有效得分 1+8+9=18。
示例 2:
输入:cards = [3,3,1], cnt = 1
输出:0
解释:不存在获取有效得分的卡牌方案。
提示:
1 <= cnt <= cards.length <= 10^5
1 <= cards[i] <= 1000
class Solution {
public int maxmiumScore(int[] cards, int cnt) {
}
}
解题思路
- 排序卡牌:将卡牌按照数字从大到小排序。
- 选择最大和的卡牌:从排序后的卡牌中选取前 cnt 张卡牌,如果这些卡牌的和为偶数,那么这是最大的有效得分。
- 调整选择:
- 如果选出的 cnt 张卡牌和为奇数,我们需要替换其中一张卡牌,使得总和变为偶数。我们可以通过查找 cnt 张卡牌中最小的奇数,并将它替换为剩下卡牌中的最大偶数(或者反过来:查找最小的偶数,替换为最大的奇数),这样可能会得到一个有效的方案。
- 如果没有符合条件的替换方案,那么返回 0。
代码示例
class Solution {
public int maxmiumScore(int[] cards, int cnt) {
int sum = 0;
int length = cards.length;
// 从大到小排序
Arrays.sort(cards);
// 将最后 cnt 个数相加
for (int i = length - 1; i > length - cnt - 1; i--) {
sum += cards[i];
}
// 判断奇偶性
if (sum % 2 == 0) {
return sum;
} else {
int minOddIn = -1;
int minEvenIn = -1;
int maxOddOut = -1;
int maxEvenOut = -1;
for (int i = length - 1; i >= length - cnt; i--) {
// 寻找 cnt 内的最小偶数
if (cards[i] % 2 == 0) {
if (minEvenIn == -1 || cards[i] < minEvenIn) {
minEvenIn = cards[i];
}
} else {
// 寻找 cnt 内的最小奇数
if (minOddIn == -1 || cards[i] < minOddIn) {
minOddIn = cards[i];
}
}
}
for (int i = length - cnt - 1; i >= 0; i--) {
// 寻找 cnt 外的最大偶数
if (cards[i] % 2 == 0) {
if (maxEvenOut == -1 || cards[i] > maxEvenOut) {
maxEvenOut = cards[i];
}
} else {
// 寻找 cnt 外的最大奇数
if (maxOddOut == -1 || cards[i] > maxOddOut) {
maxOddOut = cards[i];
}
}
}
// 修改结果
int result1 = (minOddIn != -1 && maxEvenOut != -1) ? sum - minOddIn + maxEvenOut : -1;
int result2 = (minEvenIn != -1 && maxOddOut != -1) ? sum - minEvenIn + maxOddOut : -1;
// 选出最大值
int maxSum = Math.max(result1, result2);
return maxSum == -1 ? 0 : maxSum;
}
}
}